class MikiWindow(QMainWindow): def __init__(self, settings, parent=None): super(MikiWindow, self).__init__(parent) self.setObjectName("mikiWindow") self.settings = settings self.notePath = settings.notePath lockPath = os.path.join(settings.notebookPath, '.mikidown_lock') if not os.path.exists(lockPath): self.lockPathFH = os.open(lockPath, os.O_CREAT | os.O_EXCL | os.O_RDWR) ################ Setup core components ################ self.notesTree = MikiTree(self) self.quickNoteNav = QLineEdit() self.notesTab = QWidget() self.completer = SlashPleter() self.completer.setModel(self.notesTree.model()) self.quickNoteNav.setCompleter(self.completer) self.notesTree.setObjectName("notesTree") self.initTree(self.notePath, self.notesTree) self.notesTree.sortItems(0, Qt.AscendingOrder) self.ix = None self.setupWhoosh() self.viewedList = QToolBar(self.tr('Recently Viewed'), self) self.viewedList.setIconSize(QSize(16, 16)) self.viewedList.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.viewedListActions = [] self.noteSplitter = QSplitter(Qt.Horizontal) self.dockIndex = QDockWidget(self.tr("Index")) self.dockSearch = QDockWidget(self.tr("Search")) self.searchEdit = QLineEdit() self.searchView = MikiSearch(self) self.searchTab = QWidget() self.dockToc = QDockWidget(self.tr("TOC")) self.tocTree = TocTree() self.dockAttachment = QDockWidget(self.tr("Attachment")) self.attachmentView = AttachmentView(self) self.notesEdit = MikiEdit(self) self.notesEdit.setObjectName(self.tr("notesEdit")) self.loadHighlighter() self.notesView = MikiView(self) self.findBar = QToolBar(self.tr('Find'), self) self.findBar.setFixedHeight(30) self.findEdit = QLineEdit(self.findBar) self.checkBox = QCheckBox(self.tr('Match case'), self.findBar) self.statusBar = QStatusBar(self) self.statusLabel = QLabel(self) self.altPressed = False ################ Setup actions ################ self.actions = dict() self.setupActions() ################ Setup mainwindow ################ self.setupMainWindow() # show changelogs after upgrade mikidown if self.settings.version < __version__ or Mikibook.settings.value( "version", defaultValue="0") < __version__: self.changelogHelp() self.settings.qsettings.setValue("version", __version__) Mikibook.settings.setValue("version", __version__) def loadHighlighter(self): fnt = Mikibook.settings.value('editorFont', defaultValue=None) fntsize = Mikibook.settings.value('editorFontSize', type=int, defaultValue=12) header_scales_font = Mikibook.settings.value('headerScaleFont', type=bool, defaultValue=True) if fnt is not None: self.notesEdit.setFontFamily(fnt) self.notesEdit.setFontPointSize(fntsize) h = MikiHighlighter(parent=self.notesEdit, scale_font_sizes=header_scales_font) tw = Mikibook.settings.value('tabWidth', type=int, defaultValue=4) qfm = QFontMetrics(h.patterns[0][1].font()) self.notesEdit.setTabStopWidth(tw * qfm.width(' ')) def setupActions(self): # Global Actions actTabIndex = self.act(self.tr('Switch to Index Tab'), lambda: self.raiseDock(self.dockIndex), self.tr('Ctrl+Shift+I')) actTabSearch = self.act(self.tr('Switch to Search Tab'), lambda: self.raiseDock(self.dockSearch), self.tr('Ctrl+Shift+F')) self.addAction(actTabIndex) self.addAction(actTabSearch) ################ Menu Actions ################ # actions in menuFile actionNewPage = self.act(self.tr('&New Page...'), self.notesTree.newPage, QKeySequence.New) self.actions.update(newPage=actionNewPage) actionNewSubpage = self.act(self.tr('New Sub&page...'), self.notesTree.newSubpage, self.tr('Ctrl+Shift+N')) self.actions.update(newSubpage=actionNewSubpage) actionImportPage = self.act(self.tr('&Import Page...'), self.importPage) self.actions.update(importPage=actionImportPage) actionNBSettings = self.act(self.tr('Notebook Set&tings...'), self.notebookSettings) self.actions.update(NBSettings=actionNBSettings) actionMDSettings = self.act(self.tr('&Mikidown Settings...'), self.mikidownSettings) self.actions.update(MDSettings=actionMDSettings) actionOpenNotebook = self.act(self.tr('&Open Notebook...'), self.openNotebook, QKeySequence.Open) self.actions.update(openNotebook=actionOpenNotebook) actionReIndex = self.act(self.tr('Re-index'), self.reIndex) self.actions.update(reIndex=actionReIndex) actionSave = self.act(self.tr('&Save'), self.saveCurrentNote, QKeySequence.Save) actionSave.setEnabled(False) self.actions.update(save=actionSave) actionSaveAs = self.act(self.tr('Save &As...'), self.saveNoteAs, QKeySequence.SaveAs) self.actions.update(saveAs=actionSaveAs) actionHtml = self.act(self.tr('to &HTML'), self.notesEdit.saveAsHtml) self.actions.update(html=actionHtml) actionPrint = self.act(self.tr('&Print'), self.printNote, QKeySequence.Print) self.actions.update(print_=actionPrint) actionRenamePage = self.act(self.tr('&Rename Page...'), self.notesTree.renamePage, 'F2') self.actions.update(renamePage=actionRenamePage) actionDelPage = self.act(self.tr('&Delete Page'), self.notesTree.delPageWrapper, QKeySequence.Delete) self.actions.update(delPage=actionDelPage) actionQuit = self.act(self.tr('&Quit'), self.close, QKeySequence.Quit) actionQuit.setMenuRole(QAction.QuitRole) self.actions.update(quit=actionQuit) # actions in menuEdit actionUndo = self.act(self.tr('&Undo'), lambda: self.notesEdit.undo(), QKeySequence.Undo) actionUndo.setEnabled(False) self.notesEdit.undoAvailable.connect(actionUndo.setEnabled) self.actions.update(undo=actionUndo) actionRedo = self.act(self.tr('&Redo'), lambda: self.notesEdit.redo(), QKeySequence.Redo) actionRedo.setEnabled(False) self.notesEdit.redoAvailable.connect(actionRedo.setEnabled) self.actions.update(redo=actionRedo) actionFindText = self.act(self.tr('&Find Text'), self.findBar.setVisible, QKeySequence.Find, True) self.actions.update(findText=actionFindText) actionFindRepl = self.act(self.tr('Find and Replace'), FindReplaceDialog(self.notesEdit).open, QKeySequence.Replace) self.actions.update(findRepl=actionFindRepl) actionFind = self.act(self.tr('Next'), self.findText, QKeySequence.FindNext) self.actions.update(find=actionFind) actionFindPrev = self.act(self.tr('Previous'), lambda: self.findText(back=True), QKeySequence.FindPrevious) self.actions.update(findPrev=actionFindPrev) actionSortLines = self.act(self.tr('&Sort Lines'), self.sortLines) self.actions.update(sortLines=actionSortLines) actionQuickNav = self.act(self.tr("&Quick Open Note"), self.quickNoteNav.setFocus, self.tr('Ctrl+G')) self.addAction(actionQuickNav) actionInsertImage = self.act(self.tr('&Insert Attachment'), self.notesEdit.insertAttachmentWrapper, self.tr('Ctrl+I')) actionInsertImage.setEnabled(False) self.actions.update(insertImage=actionInsertImage) # actions in menuView QIcon.setThemeName( Mikibook.settings.value('iconTheme', QIcon.themeName())) #print(QIcon.themeName()) actionEdit = self.act(self.tr('Edit'), self.edit, self.tr('Ctrl+E'), True, QIcon.fromTheme('document-edit'), self.tr('Edit mode (Ctrl+E)')) self.actions.update(edit=actionEdit) actionSplit = self.act(self.tr('Split'), self.liveView, self.tr('Ctrl+R'), True, QIcon.fromTheme('view-split-left-right'), self.tr('Split mode (Ctrl+R)')) self.actions.update(split=actionSplit) actionFlipEditAndView = self.act(self.tr('Flip Edit and View'), self.flipEditAndView) actionFlipEditAndView.setEnabled(False) self.actions.update(flipEditAndView=actionFlipEditAndView) #actionLeftAndRight = self.act( # self.tr('Split into Left and Right'), trig=self.leftAndRight) #actionUpAndDown = self.act( # self.tr('Split into Up and Down'), trig=self.upAndDown) # self.actionLeftAndRight.setEnabled(False) # self.actionUpAndDown.setEnabled(False) # actions in menuHelp actionReadme = self.act(self.tr('README'), self.readmeHelp) self.actions.update(readme=actionReadme) actionChangelog = self.act(self.tr('Changelog'), self.changelogHelp) self.actions.update(changelog=actionChangelog) actionAboutQt = self.act(self.tr('About Qt'), qApp.aboutQt) self.actions.update(aboutQt=actionAboutQt) def setupMainWindow(self): self.resize(800, 600) screen = QDesktopWidget().screenGeometry() size = self.geometry() self.move((screen.width() - size.width()) / 2, (screen.height() - size.height()) / 2) self.setWindowTitle('{} - {}'.format(self.settings.notebookName, __appname__)) self.viewedList.setFixedHeight(25) self.noteSplitter.addWidget(self.notesEdit) self.noteSplitter.addWidget(self.notesView) mainSplitter = QSplitter(Qt.Vertical) mainSplitter.setChildrenCollapsible(False) mainSplitter.addWidget(self.viewedList) mainSplitter.addWidget(self.noteSplitter) mainSplitter.addWidget(self.findBar) self.setCentralWidget(mainSplitter) self.searchEdit.returnPressed.connect(self.searchNote) self.quickNoteNav.returnPressed.connect(self.openFuncWrapper) searchLayout = QVBoxLayout() searchLayout.addWidget(self.searchEdit) searchLayout.addWidget(self.searchView) self.searchTab.setLayout(searchLayout) indexLayout = QVBoxLayout(self.notesTab) indexLayout.addWidget(self.quickNoteNav) indexLayout.addWidget(self.notesTree) self.dockIndex.setObjectName("Index") self.dockIndex.setWidget(self.notesTab) self.dockSearch.setObjectName("Search") self.dockSearch.setWidget(self.searchTab) self.dockToc.setObjectName("TOC") self.dockToc.setWidget(self.tocTree) self.dockAttachment.setObjectName("Attachment") self.dockAttachment.setWidget(self.attachmentView) self.setDockOptions(QMainWindow.VerticalTabs) self.addDockWidget(Qt.LeftDockWidgetArea, self.dockIndex) self.addDockWidget(Qt.LeftDockWidgetArea, self.dockSearch) self.addDockWidget(Qt.LeftDockWidgetArea, self.dockToc) self.addDockWidget(Qt.LeftDockWidgetArea, self.dockAttachment) self.tabifyDockWidget(self.dockIndex, self.dockSearch) self.tabifyDockWidget(self.dockSearch, self.dockToc) self.tabifyDockWidget(self.dockToc, self.dockAttachment) self.setTabPosition(Qt.LeftDockWidgetArea, QTabWidget.North) self.dockIndex.raise_() # Put dockIndex on top of the tab stack menuBar = QMenuBar(self) self.setMenuBar(menuBar) menuFile = menuBar.addMenu(self.tr('&File')) menuEdit = menuBar.addMenu(self.tr('&Edit')) menuView = menuBar.addMenu(self.tr('&View')) menuHelp = menuBar.addMenu(self.tr('&Help')) # menuFile menuFile.addAction(self.actions['newPage']) menuFile.addAction(self.actions['newSubpage']) menuFile.addAction(self.actions['NBSettings']) menuFile.addAction(self.actions['MDSettings']) menuFile.addAction(self.actions['importPage']) menuFile.addAction(self.actions['openNotebook']) menuFile.addAction(self.actions['reIndex']) menuFile.addSeparator() menuFile.addAction(self.actions['save']) menuFile.addAction(self.actions['saveAs']) menuFile.addAction(self.actions['print_']) menuExport = menuFile.addMenu(self.tr('&Export')) menuExport.addAction(self.actions['html']) menuFile.addSeparator() menuFile.addAction(self.actions['renamePage']) menuFile.addAction(self.actions['delPage']) menuFile.addSeparator() menuFile.addAction(self.actions['quit']) # menuEdit menuEdit.addAction(self.actions['undo']) menuEdit.addAction(self.actions['redo']) menuEdit.addAction(self.actions['findText']) menuEdit.addAction(self.actions['findRepl']) menuEdit.addSeparator() menuEdit.addAction(self.actions['sortLines']) menuEdit.addAction(self.actions['insertImage']) # menuView menuView.addAction(self.actions['edit']) menuView.addAction(self.actions['split']) menuView.addAction(self.actions['flipEditAndView']) menuShowHide = menuView.addMenu(self.tr('Show/Hide')) menuShowHide.addAction(self.dockIndex.toggleViewAction()) menuShowHide.addAction(self.dockSearch.toggleViewAction()) menuShowHide.addAction(self.dockToc.toggleViewAction()) menuShowHide.addAction(self.dockAttachment.toggleViewAction()) #menuMode = menuView.addMenu(self.tr('Mode')) #menuMode.addAction(self.actionLeftAndRight) #menuMode.addAction(self.actionUpAndDown) # menuHelp menuHelp.addAction(self.actions['readme']) menuHelp.addAction(self.actions['changelog']) menuHelp.addAction(self.actions['aboutQt']) toolBar = QToolBar(self.tr("toolbar"), self) toolBar.setObjectName("toolbar") # needed in saveState() #toolBar.setIconSize(QSize(16, 16)) toolBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.addToolBar(Qt.TopToolBarArea, toolBar) toolBar.addAction(self.actions['edit']) toolBar.addAction(self.actions['split']) self.findEdit.returnPressed.connect(self.findText) self.findBar.addWidget(self.findEdit) self.findBar.addWidget(self.checkBox) self.findBar.addAction(self.actions['findPrev']) self.findBar.addAction(self.actions['find']) self.findBar.setVisible(False) self.findBar.visibilityChanged.connect(self.findBarVisibilityChanged) self.setStatusBar(self.statusBar) self.statusBar.addWidget(self.statusLabel, 1) self.notesTree.currentItemChanged.connect( self.currentItemChangedWrapper) self.notesTree.nvwCallback = self.newNoteDisplay self.notesTree.nvwtCallback = self.newPlainTextNoteDisplay self.tocTree.itemClicked.connect(self.tocNavigate) self.notesEdit.textChanged.connect(self.noteEditted) self.notesEdit.document().modificationChanged.connect( self.modificationChanged) self.updateRecentViewedNotes() notes = self.settings.recentViewedNotes() if len(notes) != 0: item = self.notesTree.pageToItem(notes[0]) self.notesTree.setCurrentItem(item) def newNoteDisplay(self, item, anchor=None): msn = MikiSepNote(self.settings, item.text(0), self.notesTree.itemToFile(item), plain_text=False, parent=self) if anchor: msn.note_view.page().mainFrame().scrollToAnchor(anchor) msn.show() def newPlainTextNoteDisplay(self, item, anchor=None): msn = MikiSepNote(self.settings, item.text(0), self.notesTree.itemToFile(item), plain_text=True, parent=self) if anchor: item = msn.findItemByAnchor(anchor)[0] msn.tocNavigate(item) msn.show() def openFuncWrapper(self): self.openFunction(self.quickNoteNav.text())() def setupWhoosh(self): # Initialize whoosh index, make sure notePath/.indexdir exists indexdir = self.settings.indexdir try: self.ix = open_dir(indexdir) except: QDir().mkpath(indexdir) self.ix = create_in(indexdir, self.settings.schema) # Fork a process to update index, which benefit responsiveness. p = Thread(target=self.whoosh_index, args=()) p.start() def restore(self): """ Restore saved geometry and state. Set the status of side panels in View Menu correspondently. """ if self.settings.geometry: self.restoreGeometry(self.settings.geometry) if self.settings.windowstate: self.restoreState(self.settings.windowstate) def initTree(self, notePath, parent): ''' When there exist foo.md, foo.mkd, foo.markdown, only one item will be shown in notesTree. ''' if not QDir(notePath).exists(): return notebookDir = QDir(notePath) notesList = notebookDir.entryInfoList(['*.md', '*.mkd', '*.markdown'], QDir.NoFilter, QDir.Name | QDir.IgnoreCase) nl = [note.completeBaseName() for note in notesList] noduplicate = list(set(nl)) for name in noduplicate: item = QTreeWidgetItem(parent, [name]) path = notePath + '/' + name self.initTree(path, item) def updateToc(self): ''' TOC is updated in `updateView` tocTree fields: [hdrText, hdrPosition, hdrAnchor] ''' root = self.notesTree.currentPage() strip_math_for_header_parsing = False strip_fence_for_header_parsing = False if 'asciimathml' in self.settings.extensions: strip_math_for_header_parsing = True if 'fenced_code' in self.settings.extensions or 'extra' in self.settings.extensions: strip_fence_for_header_parsing = True self.tocTree.updateToc( root, parseHeaders(self.notesEdit.toPlainText(), strip_fenced_block=strip_fence_for_header_parsing, strip_ascii_math=strip_math_for_header_parsing)) def updateAttachmentView(self): # Update attachmentView to show corresponding attachments. item = self.notesTree.currentItem() index = self.attachmentView.model.index( self.notesTree.itemToAttachmentDir(item)) self.attachmentView.setRootIndex(index) def openFile(self, filename): fh = QFile(filename) try: if not fh.open(QIODevice.ReadOnly): raise IOError(fh.errorString()) except IOError as e: QMessageBox.warning( self, self.tr('Read Error'), self.tr('Failed to open %s: %s') % (filename, e)) finally: if fh is not None: noteBody = QTextStream(fh).readAll() fh.close() self.notesEdit.setPlainText(noteBody) self.notesView.scrollPosition = QPoint(0, 0) # self.actionSave.setEnabled(False) self.notesEdit.document().setModified(False) self.notesView.updateView() self.setCurrentNote() self.updateRecentViewedNotes() #self.statusLabel.setText(noteFullName) def currentItemChangedWrapper(self, current, previous): if current is None: return #if previous != None and self.notesTree.pageExists(previous): prev = self.notesTree.itemToPage(previous) if self.notesTree.pageExists(prev): self.saveNote(previous) currentFile = self.notesTree.itemToFile(current) self.openFile(currentFile) # Update attachmentView to show corresponding attachments. index = self.attachmentView.model.index( self.notesTree.itemToAttachmentDir(current)) self.attachmentView.setRootIndex(index) def tocNavigate(self, current): ''' works for notesEdit now ''' if current is None: return pos = int(current.text(1)) link = "file://" + self.notePath + "/#" + current.text(2) # Move cursor to END first will ensure # header is positioned at the top of visual area. self.notesEdit.moveCursor(QTextCursor.End) cur = self.notesEdit.textCursor() cur.setPosition(pos, QTextCursor.MoveAnchor) self.notesEdit.setTextCursor(cur) self.notesView.load(QUrl(link)) def switchNote(self, num): if num < len(self.viewedListActions): self.viewedListActions[num].trigger() def saveCurrentNote(self): item = self.notesTree.currentItem() self.saveNote(item) def saveNote(self, item): if self.notesEdit.document().isModified(): self.notesEdit.document().setModified(False) else: return self.notesEdit.save(item) def saveNoteAs(self): self.saveCurrentNote() fileName = QFileDialog.getSaveFileName( self, self.tr('Save as'), '', '(*.md *.mkd *.markdown);;' + self.tr('All files(*)')) if fileName == '': return if not QFileInfo(fileName).suffix(): fileName += '.md' fh = QFile(fileName) fh.open(QIODevice.WriteOnly) savestream = QTextStream(fh) savestream << self.notesEdit.toPlainText() fh.close() def printNote(self): printer = QPrinter(QPrinter.HighResolution) printer.setCreator(__appname__ + ' ' + __version__) printer.setDocName(self.notesTree.currentItem().text(0)) printdialog = QPrintDialog(printer, self) if printdialog.exec() == QDialog.Accepted: self.notesView.print_(printer) def noteEditted(self): """ Continuously get fired while editing""" self.updateToc() self.notesView.updateLiveView() def modificationChanged(self, changed): """ Fired one time: modified or not """ self.actions['save'].setEnabled(changed) name = self.notesTree.currentPage() self.statusBar.clearMessage() if changed: self.statusLabel.setText(name + '*') else: self.statusLabel.setText(name) def importPage(self): filename = QFileDialog.getOpenFileName( self, self.tr('Import file'), '', '(*.md *.mkd *.markdown *.txt);;' + self.tr('All files(*)')) if filename == '': return self.importPageCore(filename) def importPageCore(self, filename): fh = QFile(filename) fh.open(QIODevice.ReadOnly) fileBody = QTextStream(fh).readAll() fh.close() page = QFileInfo(filename).completeBaseName() fh = QFile(self.notesTree.pageToFile(page)) if fh.exists(): QMessageBox.warning(self, self.tr("Import Error"), self.tr("Page already exists: %s") % page) dialog = LineEditDialog(self.notePath, self) if dialog.exec_(): page = dialog.editor.text() fh.close() fh = QFile(self.notesTree.pageToFile(page)) else: return fh.open(QIODevice.WriteOnly) savestream = QTextStream(fh) savestream << fileBody fh.close() item = QTreeWidgetItem(self.notesTree, [page]) self.notesTree.sortItems(0, Qt.AscendingOrder) self.notesTree.setCurrentItem(item) def openNotebook(self): dialog = NotebookListDialog(self) if dialog.exec_(): pass def notebookSettings(self): dialog = NotebookSettingsDialog(self) if dialog.exec_(): pass def mikidownSettings(self): dialog = MikidownCfgDialog(self) if dialog.exec_(): pass def reIndex(self): """ Whoosh index breaks for unknown reasons (sometimes) """ shutil.rmtree(self.settings.indexdir) self.setupWhoosh() def act(self, name, trig, shortcut=None, checkable=False, icon=None, tooltip=None): """ A wrapper to several QAction methods """ if icon: action = QAction(icon, name, self) else: action = QAction(name, self) if shortcut: action.setShortcut(QKeySequence(shortcut)) action.setCheckable(checkable) if tooltip: action.setToolTip(tooltip) action.triggered.connect(trig) return action def edit(self, viewmode): """ Switch between EDIT and VIEW mode. """ if self.actions['split'].isChecked(): self.actions['split'].setChecked(False) self.notesView.setVisible(not viewmode) self.notesEdit.setVisible(viewmode) # Gives the keyboard input focus to notesEdit/notesView. # Without this, keyboard input may change note text even when # notesEdit is invisible. if viewmode: self.notesEdit.setFocus() else: self.notesView.setFocus() self.saveCurrentNote() self.actions['insertImage'].setEnabled(viewmode) #self.actionLeftAndRight.setEnabled(True) #self.actionUpAndDown.setEnabled(True) # Render the note text as it is. self.notesView.updateView() def liveView(self, viewmode): """ Switch between VIEW and LIVE VIEW mode. """ self.actions['split'].setChecked(viewmode) sizes = self.noteSplitter.sizes() if self.actions['edit'].isChecked(): self.actions['edit'].setChecked(False) self.notesView.setVisible(viewmode) splitSize = [sizes[0] * 0.45, sizes[0] * 0.55] else: self.notesEdit.setVisible(viewmode) splitSize = [sizes[1] * 0.45, sizes[1] * 0.55] # setFocus for the same reason as in edit(self, viewmode) if viewmode: self.notesEdit.setFocus() else: self.notesView.setFocus() self.actions['flipEditAndView'].setEnabled(viewmode) #self.actionUpAndDown.setEnabled(viewmode) self.actions['insertImage'].setEnabled(viewmode) self.noteSplitter.setSizes(splitSize) self.saveCurrentNote() # Render the note text as it is. self.notesView.updateView() def findBarVisibilityChanged(self, visible): self.actions['findText'].setChecked(visible) if visible: self.findEdit.setFocus(Qt.ShortcutFocusReason) def findText(self, back=False): flags = 0 if back: flags = QTextDocument.FindBackward if self.checkBox.isChecked(): flags = flags | QTextDocument.FindCaseSensitively text = self.findEdit.text() if not self.findMain(text, flags): if text in self.notesEdit.toPlainText(): cursor = self.notesEdit.textCursor() if back: cursor.movePosition(QTextCursor.End) else: cursor.movePosition(QTextCursor.Start) self.notesEdit.setTextCursor(cursor) self.findMain(text, flags) # self.notesView.findText(text, flags) def findMain(self, text, flags): viewFlags = QWebPage.FindFlags( flags) | QWebPage.FindWrapsAroundDocument if flags: self.notesView.findText(text, viewFlags) return self.notesEdit.find(text, flags) else: self.notesView.findText(text) return self.notesEdit.find(text) def sortLines(self): ''' sort selected lines TODO: second sort reverse the order ''' cursor = self.notesEdit.textCursor() start = cursor.selectionStart() end = cursor.selectionEnd() cursor.setPosition(start) cursor.movePosition(QTextCursor.StartOfLine) cursor.setPosition(end, mode=QTextCursor.KeepAnchor) cursor.movePosition(QTextCursor.EndOfLine, mode=QTextCursor.KeepAnchor) text = cursor.selectedText() lines = text.split('\u2029') # '\u2029' is the line break sortedLines = sorted(lines) cursor.insertText('\n'.join(sortedLines)) def notesEditInFocus(self, e): if e.gotFocus: self.actions['insertImage'].setEnabled(True) # if e.lostFocus: # self.actionInsertImage.setEnabled(False) # QWidget.focusInEvent(self,f) def searchNote(self): """ Sorting criteria: "title > path > content" Search matches are organized into html source. """ pattern = self.searchEdit.text() if not pattern: return results = [] print("Searching using", pattern) with self.ix.searcher() as searcher: matches = [] queryp = QueryParser("content", self.ix.schema) #allow escaped qutoes when regex searching queryp.add_plugin( RegexPlugin(expr=r'r"(?P<text>[^"\\]*(\\.[^"\\]*)*)"')) # ~~r"pattern" is the desired regex term format~~ Don't autoforce regexing query = queryp.parse(pattern) #print("durp durp", query) ms = searcher.search(query, limit=None) # default limit is 10! for m in ms: #if not m in matches: matches.append(m) for r in matches: title = r['title'] path = r['path'] term = r.highlights("content") results.append([title, path, term]) html = "" for title, path, hi in results: html += ("<p><a href='" + path + "'>" + title + "</a><br/><span class='path'>" + path + "</span><br/>" + hi + "</p>") self.searchView.setHtml(html) print("Finished searching", pattern) def whoosh_index(self): it = QTreeWidgetItemIterator(self.notesTree, QTreeWidgetItemIterator.All) print("Starting complete indexing.") #writer = self.ix.writer() writer = AsyncWriter(self.ix) while it.value(): treeItem = it.value() name = self.notesTree.itemToPage(treeItem) path = os.path.join(self.notesTree.pageToFile(name)).replace( os.sep, '/') print(path) fileobj = open(path, 'r', encoding='utf-8') content = fileobj.read() fileobj.close() if METADATA_CHECKER.match( content) and 'meta' in self.settings.extensions: no_metadata_content = METADATA_CHECKER.sub("", content, count=1).lstrip() self.settings.md.reset().convert(content) writer.update_document( path=name, title=parseTitle(content, name), content=no_metadata_content, tags=','.join(self.settings.md.Meta.get('tags', [])).strip()) else: writer.add_document(path=name, title=parseTitle(content, name), content=content, tags='') it += 1 writer.commit() print("Finished completely reindexing.") def listItemChanged(self, row): if row != -1: item = self.searchList.currentItem().data(Qt.UserRole) self.notesTree.setCurrentItem(item) flags = QWebPage.HighlightAllOccurrences self.notesView.findText(self.searchEdit.text(), flags) def setCurrentNote(self): item = self.notesTree.currentItem() name = self.notesTree.itemToPage(item) # Current note is inserted to head of list. notes = self.settings.recentViewedNotes() for f in notes: if f == name: notes.remove(f) notes.insert(0, name) recent_notes_n = Mikibook.settings.value('recentNotesNumber', type=int, defaultValue=20) if len(notes) > recent_notes_n: del notes[recent_notes_n:] self.settings.updateRecentViewedNotes(notes) def updateRecentViewedNotes(self): """ Switching notes will trigger this. When Alt pressed, show note number. """ self.viewedList.clear() self.viewedListActions = [] # Check notes exists. viewedNotes = self.settings.recentViewedNotes() existedNotes = [] i = 0 for f in viewedNotes: if self.notesTree.pageExists(f): existedNotes.append(f) names = f.split('/') if self.altPressed and i in range(1, 10): action = self.act(names[-1], self.openFunction(f), 'Alt+' + str(i), True, ViewedNoteIcon(i), 'Alt+' + str(i)) else: action = self.act(names[-1], self.openFunction(f), None, True) self.viewedListActions.append(action) i += 1 if not self.altPressed: self.settings.updateRecentViewedNotes(existedNotes) for action in self.viewedListActions: self.viewedList.addAction(action) if len(self.viewedListActions): self.viewedListActions[0].setChecked(True) def openFunction(self, name): item = self.notesTree.pageToItem(name) return lambda: self.notesTree.setCurrentItem(item) def raiseDock(self, widget): if not widget.isVisible(): widget.show() if widget == self.dockSearch: self.searchEdit.setFocus() widget.raise_() def flipEditAndView(self): index = self.noteSplitter.indexOf(self.notesEdit) if index == 0: self.noteSplitter.insertWidget(1, self.notesEdit) else: self.noteSplitter.insertWidget(0, self.notesEdit) def leftAndRight(self): self.liveView(True) self.noteSplitter.setOrientation(Qt.Horizontal) #self.actionLeftAndRight.setEnabled(False) #self.actionUpAndDown.setEnabled(True) def upAndDown(self): self.liveView(True) self.noteSplitter.setOrientation(Qt.Vertical) #self.actionUpAndDown.setEnabled(False) #self.actionLeftAndRight.setEnabled(True) def readmeHelp(self): readmeFile = '/usr/share/mikidown/README.mkd' if not os.path.exists(readmeFile): readmeFile = os.path.join( os.path.dirname(os.path.dirname(__file__)), 'README.mkd').replace(os.sep, '/') self.importPageCore(readmeFile) def changelogHelp(self): changeLog = "/usr/share/mikidown/Changelog.md" if not os.path.exists(changeLog): changeLog = os.path.join( os.path.dirname(os.path.dirname(__file__)), 'Changelog.md').replace(os.sep, '/') self.importPageCore(changeLog) def keyPressEvent(self, event): """ When Alt pressed, note number will be shown in viewedList. """ if event.key() == Qt.Key_Alt: self.altPressed = True self.updateRecentViewedNotes() else: QMainWindow.keyPressEvent(self, event) def keyReleaseEvent(self, event): if event.key() == Qt.Key_Alt: self.altPressed = False self.updateRecentViewedNotes() else: QMainWindow.keyPressEvent(self, event) def closeEvent(self, event): """ saveGeometry: Saves the current geometry and state for top-level widgets saveState: Restores the state of this mainwindow's toolbars and dockwidgets """ self.saveCurrentNote() self.ix.close() self.notesEdit.ix.close() if hasattr(self.notesTree, 'ix'): self.notesTree.ix.close() self.settings.saveGeometry(self.saveGeometry()) self.settings.saveWindowState(self.saveState()) event.accept() os.close(self.lockPathFH) lockPath = os.path.join(self.settings.notebookPath, '.mikidown_lock') os.remove(lockPath)
def lauchGUI(self, WorkSpace, aCase, sobjXML, Args): """ mw.dockWidgetBrowser is the Browser of the CFD MainView """ log.debug("lauchGUI") from cs_gui import process_cmd_line if CFD_Code() == CFD_Saturne: from cs_package import package from code_saturne.Base.MainView import MainView elif CFD_Code() == CFD_Neptune: from nc_package import package from neptune_cfd.core.MainView import MainView if sobjXML == None: Title = "unnamed" else: Title = sobjXML.GetName() self.Workspace = WorkSpace pkg = package() case, splash = process_cmd_line(Args) mw = MainView(pkg, case, aCase) # Put the standard panel of the MainView inside a QDockWidget # in the SALOME Desktop aTitle = self.setWindowTitle_CFD(mw, aCase, Title) dsk = sgPyQt.getDesktop() dock = QDockWidget(aTitle) dock.setWidget(mw.frame) dock.setMinimumWidth(520) dsk.addDockWidget(Qt.RightDockWidgetArea, dock) dock.setVisible(True) dock.show() # Put the QTreeView of the MainView which is already inside a QDockWidget # in the SALOME Desktop BrowserTitle = aTitle + " Browser" mw.dockWidgetBrowser.setWindowTitle(BrowserTitle) dsk.addDockWidget(Qt.LeftDockWidgetArea, mw.dockWidgetBrowser) mw.dockWidgetBrowser.setVisible(True) mw.dockWidgetBrowser.show() mw.dockWidgetBrowser.raise_() dock.raise_() #Add Dock windows are managed by CFDGUI_Management class studyId = sgPyQt.getStudyId() aStudyCFD = aCase.GetFather() aCaseCFD = aCase xmlFileName = str(Title) _c_CFDGUI.set_d_CfdCases(studyId, dock, mw.dockWidgetBrowser, mw, aStudyCFD, aCaseCFD, xmlFileName, sobjXML) self.connect(dock, SIGNAL("visibilityChanged(bool)"), self.setdockWindowBrowserActivated) self.connect(mw.dockWidgetBrowser, SIGNAL("visibilityChanged(bool)"),self.setdockWindowActivated) self.connect(dock.toggleViewAction(), SIGNAL("toggled(bool)"), self.setdockWB) self.connect(mw.dockWidgetBrowser.toggleViewAction(), SIGNAL("toggled(bool)"), self.setdock) _c_CFDGUI.tabifyDockWindows(dsk, studyId) self.showDockWindows(studyId, xmlFileName, aCaseCFD.GetName(), aStudyCFD.GetName()) updateObjectBrowser() return mw
class MikiWindow(QMainWindow): def __init__(self, settings, parent=None): super(MikiWindow, self).__init__(parent) self.setObjectName("mikiWindow") self.settings = settings self.notePath = settings.notePath ################ Setup core components ################ self.notesTree = MikiTree(self) self.quickNoteNav = QLineEdit() self.notesTab = QWidget() self.completer = SlashPleter() self.completer.setModel(self.notesTree.model()) self.quickNoteNav.setCompleter(self.completer) self.notesTree.setObjectName("notesTree") self.initTree(self.notePath, self.notesTree) self.notesTree.sortItems(0, Qt.AscendingOrder) self.ix = None self.setupWhoosh() self.viewedList = QToolBar(self.tr('Recently Viewed'), self) self.viewedList.setIconSize(QSize(16, 16)) self.viewedList.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.viewedListActions = [] self.noteSplitter = QSplitter(Qt.Horizontal) self.dockIndex = QDockWidget("Index") self.dockSearch = QDockWidget("Search") self.searchEdit = QLineEdit() self.searchView = MikiSearch(self) self.searchTab = QWidget() self.dockToc = QDockWidget("TOC") self.tocTree = TocTree() self.dockAttachment = QDockWidget("Attachment") self.attachmentView = AttachmentView(self) self.notesEdit = MikiEdit(self) self.notesEdit.setObjectName("notesEdit") MikiHighlighter(self.notesEdit) self.notesView = MikiView(self) self.findBar = QToolBar(self.tr('Find'), self) self.findBar.setFixedHeight(30) self.findEdit = QLineEdit(self.findBar) self.checkBox = QCheckBox(self.tr('Match case'), self.findBar) self.statusBar = QStatusBar(self) self.statusLabel = QLabel(self) self.altPressed = False ################ Setup actions ################ self.actions = dict() self.setupActions() ################ Setup mainwindow ################ self.setupMainWindow() # show changelogs after upgrade mikidown if self.settings.version < __version__: self.changelogHelp() self.settings.qsettings.setValue("version", __version__) def setupActions(self): # Global Actions actTabIndex = self.act(self.tr('Switch to Index Tab'), lambda: self.raiseDock(self.dockIndex), 'Ctrl+Shift+I') actTabSearch = self.act(self.tr('Switch to Search Tab'), lambda: self.raiseDock(self.dockSearch), 'Ctrl+Shift+F') self.addAction(actTabIndex) self.addAction(actTabSearch) ################ Menu Actions ################ # actions in menuFile actionNewPage = self.act(self.tr('&New Page...'), self.notesTree.newPage, QKeySequence.New) self.actions.update(newPage=actionNewPage) actionNewSubpage = self.act(self.tr('New Sub&page...'), self.notesTree.newSubpage, 'Ctrl+Shift+N') self.actions.update(newSubpage=actionNewSubpage) actionImportPage = self.act(self.tr('&Import Page...'), self.importPage) self.actions.update(importPage=actionImportPage) actionNBSettings = self.act(self.tr('Notebook Set&tings...'), self.notebookSettings) self.actions.update(NBSettings=actionNBSettings) actionMDSettings = self.act(self.tr('&Mikidown Settings...'), self.mikidownSettings) self.actions.update(MDSettings=actionMDSettings) actionOpenNotebook = self.act(self.tr('&Open Notebook...'), self.openNotebook, QKeySequence.Open) self.actions.update(openNotebook=actionOpenNotebook) actionReIndex = self.act(self.tr('Re-index'), self.reIndex) self.actions.update(reIndex=actionReIndex) actionSave = self.act(self.tr('&Save'), self.saveCurrentNote, QKeySequence.Save) actionSave.setEnabled(False) self.actions.update(save=actionSave) actionSaveAs = self.act(self.tr('Save &As...'), self.saveNoteAs, QKeySequence.SaveAs) self.actions.update(saveAs=actionSaveAs) actionHtml = self.act(self.tr('to &HTML'), self.notesEdit.saveAsHtml) self.actions.update(html=actionHtml) actionPrint = self.act(self.tr('&Print'), self.printNote, QKeySequence.Print) self.actions.update(print_=actionPrint) actionRenamePage = self.act(self.tr('&Rename Page...'), self.notesTree.renamePage, 'F2') self.actions.update(renamePage=actionRenamePage) actionDelPage = self.act(self.tr('&Delete Page'), self.notesTree.delPageWrapper, QKeySequence.Delete) self.actions.update(delPage=actionDelPage) actionQuit = self.act(self.tr('&Quit'), self.close, QKeySequence.Quit) actionQuit.setMenuRole(QAction.QuitRole) self.actions.update(quit=actionQuit) # actions in menuEdit actionUndo = self.act(self.tr('&Undo'), lambda: self.notesEdit.undo(), QKeySequence.Undo) actionUndo.setEnabled(False) self.notesEdit.undoAvailable.connect(actionUndo.setEnabled) self.actions.update(undo=actionUndo) actionRedo = self.act(self.tr('&Redo'), lambda: self.notesEdit.redo(), QKeySequence.Redo) actionRedo.setEnabled(False) self.notesEdit.redoAvailable.connect(actionRedo.setEnabled) self.actions.update(redo=actionRedo) actionFindText = self.act(self.tr('&Find Text'), self.findBar.setVisible, QKeySequence.Find, True) self.actions.update(findText=actionFindText) actionFind = self.act(self.tr('Next'), self.findText, QKeySequence.FindNext) self.actions.update(find=actionFind) actionFindPrev = self.act(self.tr('Previous'), lambda: self.findText(back=True), QKeySequence.FindPrevious) self.actions.update(findPrev=actionFindPrev) actionSortLines = self.act(self.tr('&Sort Lines'), self.sortLines) self.actions.update(sortLines=actionSortLines) actionQuickNav = self.act(self.tr("&Quick Open Note"), self.quickNoteNav.setFocus, 'Ctrl+G') self.addAction(actionQuickNav) actionInsertImage = self.act(self.tr('&Insert Attachment'), self.notesEdit.insertAttachmentWrapper, 'Ctrl+I') actionInsertImage.setEnabled(False) self.actions.update(insertImage=actionInsertImage) # actions in menuView actionEdit = self.act(self.tr('Edit'), self.edit, 'Ctrl+E', True, QIcon(':/icons/edit.svg'), 'Edit mode (Ctrl+E)') self.actions.update(edit=actionEdit) actionSplit = self.act(self.tr('Split'), self.liveView, 'Ctrl+R', True, QIcon(':/icons/split.svg'), 'Split mode (Ctrl+R)') self.actions.update(split=actionSplit) actionFlipEditAndView = self.act(self.tr('Flip Edit and View'), self.flipEditAndView) actionFlipEditAndView.setEnabled(False) self.actions.update(flipEditAndView=actionFlipEditAndView) #actionLeftAndRight = self.act( # self.tr('Split into Left and Right'), trig=self.leftAndRight) #actionUpAndDown = self.act( # self.tr('Split into Up and Down'), trig=self.upAndDown) # self.actionLeftAndRight.setEnabled(False) # self.actionUpAndDown.setEnabled(False) # actions in menuHelp actionReadme = self.act(self.tr('README'), self.readmeHelp) self.actions.update(readme=actionReadme) actionChangelog = self.act(self.tr('Changelog'), self.changelogHelp) self.actions.update(changelog=actionChangelog) actionAboutQt = self.act(self.tr('About Qt'), qApp.aboutQt) self.actions.update(aboutQt=actionAboutQt) def setupMainWindow(self): self.resize(800, 600) screen = QDesktopWidget().screenGeometry() size = self.geometry() self.move(( screen.width()-size.width())/2, (screen.height()-size.height())/2) self.setWindowTitle( '{} - {}'.format(self.settings.notebookName, __appname__)) self.viewedList.setFixedHeight(25) self.noteSplitter.addWidget(self.notesEdit) self.noteSplitter.addWidget(self.notesView) mainSplitter = QSplitter(Qt.Vertical) mainSplitter.setChildrenCollapsible(False) mainSplitter.addWidget(self.viewedList) mainSplitter.addWidget(self.noteSplitter) mainSplitter.addWidget(self.findBar) self.setCentralWidget(mainSplitter) self.searchEdit.returnPressed.connect(self.searchNote) self.quickNoteNav.returnPressed.connect(self.openFuncWrapper) searchLayout = QVBoxLayout() searchLayout.addWidget(self.searchEdit) searchLayout.addWidget(self.searchView) self.searchTab.setLayout(searchLayout) self.tocTree.header().close() indexLayout = QVBoxLayout(self.notesTab) indexLayout.addWidget(self.quickNoteNav) indexLayout.addWidget(self.notesTree) self.dockIndex.setObjectName("Index") self.dockIndex.setWidget(self.notesTab) self.dockSearch.setObjectName("Search") self.dockSearch.setWidget(self.searchTab) self.dockToc.setObjectName("TOC") self.dockToc.setWidget(self.tocTree) self.dockAttachment.setObjectName("Attachment") self.dockAttachment.setWidget(self.attachmentView) self.setDockOptions(QMainWindow.VerticalTabs) self.addDockWidget(Qt.LeftDockWidgetArea, self.dockIndex) self.addDockWidget(Qt.LeftDockWidgetArea, self.dockSearch) self.addDockWidget(Qt.LeftDockWidgetArea, self.dockToc) self.addDockWidget(Qt.LeftDockWidgetArea, self.dockAttachment) self.tabifyDockWidget(self.dockIndex, self.dockSearch) self.tabifyDockWidget(self.dockSearch, self.dockToc) self.tabifyDockWidget(self.dockToc, self.dockAttachment) self.setTabPosition(Qt.LeftDockWidgetArea, QTabWidget.North) self.dockIndex.raise_() # Put dockIndex on top of the tab stack menuBar = QMenuBar(self) self.setMenuBar(menuBar) menuFile = menuBar.addMenu(self.tr('&File')) menuEdit = menuBar.addMenu(self.tr('&Edit')) menuView = menuBar.addMenu(self.tr('&View')) menuHelp = menuBar.addMenu(self.tr('&Help')) # menuFile menuFile.addAction(self.actions['newPage']) menuFile.addAction(self.actions['newSubpage']) menuFile.addAction(self.actions['NBSettings']) menuFile.addAction(self.actions['MDSettings']) menuFile.addAction(self.actions['importPage']) menuFile.addAction(self.actions['openNotebook']) menuFile.addAction(self.actions['reIndex']) menuFile.addSeparator() menuFile.addAction(self.actions['save']) menuFile.addAction(self.actions['saveAs']) menuFile.addAction(self.actions['print_']) menuExport = menuFile.addMenu(self.tr('&Export')) menuExport.addAction(self.actions['html']) menuFile.addSeparator() menuFile.addAction(self.actions['renamePage']) menuFile.addAction(self.actions['delPage']) menuFile.addSeparator() menuFile.addAction(self.actions['quit']) # menuEdit menuEdit.addAction(self.actions['undo']) menuEdit.addAction(self.actions['redo']) menuEdit.addAction(self.actions['findText']) menuEdit.addSeparator() menuEdit.addAction(self.actions['sortLines']) menuEdit.addAction(self.actions['insertImage']) # menuView menuView.addAction(self.actions['edit']) menuView.addAction(self.actions['split']) menuView.addAction(self.actions['flipEditAndView']) menuShowHide = menuView.addMenu(self.tr('Show/Hide')) menuShowHide.addAction(self.dockIndex.toggleViewAction()) menuShowHide.addAction(self.dockSearch.toggleViewAction()) menuShowHide.addAction(self.dockToc.toggleViewAction()) menuShowHide.addAction(self.dockAttachment.toggleViewAction()) #menuMode = menuView.addMenu(self.tr('Mode')) #menuMode.addAction(self.actionLeftAndRight) #menuMode.addAction(self.actionUpAndDown) # menuHelp menuHelp.addAction(self.actions['readme']) menuHelp.addAction(self.actions['changelog']) menuHelp.addAction(self.actions['aboutQt']) toolBar = QToolBar(self.tr("toolbar"), self) toolBar.setObjectName("toolbar") # needed in saveState() toolBar.setIconSize(QSize(16, 16)) toolBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.addToolBar(Qt.TopToolBarArea, toolBar) toolBar.addAction(self.actions['edit']) toolBar.addAction(self.actions['split']) self.findEdit.returnPressed.connect(self.findText) self.findBar.addWidget(self.findEdit) self.findBar.addWidget(self.checkBox) self.findBar.addAction(self.actions['findPrev']) self.findBar.addAction(self.actions['find']) self.findBar.setVisible(False) self.findBar.visibilityChanged.connect(self.findBarVisibilityChanged) self.setStatusBar(self.statusBar) self.statusBar.addWidget(self.statusLabel, 1) self.notesTree.currentItemChanged.connect( self.currentItemChangedWrapper) self.tocTree.itemClicked.connect(self.tocNavigate) self.notesEdit.textChanged.connect(self.noteEditted) self.notesEdit.document( ).modificationChanged.connect(self.modificationChanged) self.updateRecentViewedNotes() notes = self.settings.recentViewedNotes() if len(notes) != 0: item = self.notesTree.pageToItem(notes[0]) self.notesTree.setCurrentItem(item) def openFuncWrapper(self): self.openFunction(self.quickNoteNav.text())() def setupWhoosh(self): # Initialize whoosh index, make sure notePath/.indexdir exists indexdir = self.settings.indexdir try: self.ix = open_dir(indexdir) except: QDir().mkpath(indexdir) self.ix = create_in(indexdir, self.settings.schema) # Fork a process to update index, which benefit responsiveness. p = Thread(target=self.whoosh_index, args=()) p.start() def restore(self): """ Restore saved geometry and state. Set the status of side panels in View Menu correspondently. """ if self.settings.geometry: self.restoreGeometry(self.settings.geometry) if self.settings.windowstate: self.restoreState(self.settings.windowstate) def initTree(self, notePath, parent): ''' When there exist foo.md, foo.mkd, foo.markdown, only one item will be shown in notesTree. ''' if not QDir(notePath).exists(): return notebookDir = QDir(notePath) notesList = notebookDir.entryInfoList(['*.md', '*.mkd', '*.markdown'], QDir.NoFilter, QDir.Name|QDir.IgnoreCase) nl = [note.completeBaseName() for note in notesList] noduplicate = list(set(nl)) for name in noduplicate: item = QTreeWidgetItem(parent, [name]) path = notePath + '/' + name self.initTree(path, item) def updateToc(self): ''' TOC is updated in `updateView` tocTree fields: [hdrText, hdrPosition, hdrAnchor] ''' root = self.notesTree.currentPage() self.tocTree.clear() item = QTreeWidgetItem(self.tocTree, [root, '0']) curLevel = 0 for (level, h, p, a) in parseHeaders(self.notesEdit.toPlainText()): val = [h, str(p), a] if level == curLevel: item = QTreeWidgetItem(item.parent(), val) elif level < curLevel: item = QTreeWidgetItem(item.parent().parent(), val) curLevel = level else: item = QTreeWidgetItem(item, val) curLevel = level self.tocTree.expandAll() def updateAttachmentView(self): # Update attachmentView to show corresponding attachments. item = self.notesTree.currentItem() index = self.attachmentView.model.index( self.notesTree.itemToAttachmentDir(item)) self.attachmentView.setRootIndex(index) def openFile(self, filename): fh = QFile(filename) try: if not fh.open(QIODevice.ReadOnly): raise IOError(fh.errorString()) except IOError as e: QMessageBox.warning(self, 'Read Error', 'Failed to open %s: %s' % (filename, e)) finally: if fh is not None: noteBody = QTextStream(fh).readAll() fh.close() self.notesEdit.setPlainText(noteBody) self.notesView.scrollPosition = QPoint(0, 0) # self.actionSave.setEnabled(False) self.notesEdit.document().setModified(False) self.notesView.updateView() self.setCurrentNote() self.updateRecentViewedNotes() #self.statusLabel.setText(noteFullName) def currentItemChangedWrapper(self, current, previous): if current is None: return #if previous != None and self.notesTree.pageExists(previous): prev = self.notesTree.itemToPage(previous) if self.notesTree.pageExists(prev): self.saveNote(previous) currentFile = self.notesTree.itemToFile(current) self.openFile(currentFile) # Update attachmentView to show corresponding attachments. index = self.attachmentView.model.index( self.notesTree.itemToAttachmentDir(current)) self.attachmentView.setRootIndex(index) def tocNavigate(self, current): ''' works for notesEdit now ''' if current is None: return pos = int(current.text(1)) link = "file://" + self.notePath + "/#" + current.text(2) # Move cursor to END first will ensure # header is positioned at the top of visual area. self.notesEdit.moveCursor(QTextCursor.End) cur = self.notesEdit.textCursor() cur.setPosition(pos, QTextCursor.MoveAnchor) self.notesEdit.setTextCursor(cur) self.notesView.load(QUrl(link)) def switchNote(self, num): if num < len(self.viewedListActions): self.viewedListActions[num].trigger() def saveCurrentNote(self): item = self.notesTree.currentItem() self.saveNote(item) def saveNote(self, item): if self.notesEdit.document().isModified(): self.notesEdit.document().setModified(False) else: return self.notesEdit.save(item) def saveNoteAs(self): self.saveCurrentNote() fileName = QFileDialog.getSaveFileName(self, self.tr('Save as'), '', '(*.md *.mkd *.markdown);;'+self.tr('All files(*)')) if fileName == '': return if not QFileInfo(fileName).suffix(): fileName += '.md' fh = QFile(fileName) fh.open(QIODevice.WriteOnly) savestream = QTextStream(fh) savestream << self.notesEdit.toPlainText() fh.close() def printNote(self): printer = QPrinter(QPrinter.HighResolution) printer.setCreator(__appname__ + ' ' + __version__) printer.setDocName(self.notesTree.currentItem().text(0)) printdialog = QPrintDialog(printer, self) if printdialog.exec() == QDialog.Accepted: self.notesView.print_(printer) def noteEditted(self): """ Continuously get fired while editing""" self.updateToc() self.notesView.updateLiveView() def modificationChanged(self, changed): """ Fired one time: modified or not """ self.actions['save'].setEnabled(changed) name = self.notesTree.currentPage() self.statusBar.clearMessage() if changed: self.statusLabel.setText(name + '*') else: self.statusLabel.setText(name) def importPage(self): filename = QFileDialog.getOpenFileName( self, self.tr('Import file'), '', '(*.md *.mkd *.markdown *.txt);;'+self.tr('All files(*)')) if filename == '': return self.importPageCore(filename) def importPageCore(self, filename): fh = QFile(filename) fh.open(QIODevice.ReadOnly) fileBody = QTextStream(fh).readAll() fh.close() page = QFileInfo(filename).completeBaseName() fh = QFile(self.notesTree.pageToFile(page)) if fh.exists(): QMessageBox.warning(self, 'Import Error', 'Page already exists: %s' % page) dialog = LineEditDialog(self.notePath, self) if dialog.exec_(): page = dialog.editor.text() fh.close() fh = QFile(self.notesTree.pageToFile(page)) else: return fh.open(QIODevice.WriteOnly) savestream = QTextStream(fh) savestream << fileBody fh.close() item = QTreeWidgetItem(self.notesTree, [page]) self.notesTree.sortItems(0, Qt.AscendingOrder) self.notesTree.setCurrentItem(item) def openNotebook(self): dialog = NotebookListDialog(self) if dialog.exec_(): pass def notebookSettings(self): dialog = NotebookSettingsDialog(self) if dialog.exec_(): pass def mikidownSettings(self): dialog = MikidownCfgDialog(self) if dialog.exec_(): pass def reIndex(self): """ Whoosh index breaks for unknown reasons (sometimes) """ shutil.rmtree(self.settings.indexdir) self.setupWhoosh() def act(self, name, trig, shortcut=None, checkable=False, icon=None, tooltip=None): """ A wrapper to several QAction methods """ if icon: action = QAction(icon, name, self) else: action = QAction(name, self) if shortcut: action.setShortcut(QKeySequence(shortcut)) action.setCheckable(checkable) if tooltip: action.setToolTip(tooltip) action.triggered.connect(trig) return action def edit(self, viewmode): """ Switch between EDIT and VIEW mode. """ if self.actions['split'].isChecked(): self.actions['split'].setChecked(False) self.notesView.setVisible(not viewmode) self.notesEdit.setVisible(viewmode) # Gives the keyboard input focus to notesEdit/notesView. # Without this, keyboard input may change note text even when # notesEdit is invisible. if viewmode: self.notesEdit.setFocus() else: self.notesView.setFocus() self.saveCurrentNote() self.actions['insertImage'].setEnabled(viewmode) #self.actionLeftAndRight.setEnabled(True) #self.actionUpAndDown.setEnabled(True) # Render the note text as it is. self.notesView.updateView() def liveView(self, viewmode): """ Switch between VIEW and LIVE VIEW mode. """ self.actions['split'].setChecked(viewmode) sizes = self.noteSplitter.sizes() if self.actions['edit'].isChecked(): self.actions['edit'].setChecked(False) self.notesView.setVisible(viewmode) splitSize = [sizes[0]*0.45, sizes[0]*0.55] else: self.notesEdit.setVisible(viewmode) splitSize = [sizes[1]*0.45, sizes[1]*0.55] # setFocus for the same reason as in edit(self, viewmode) if viewmode: self.notesEdit.setFocus() else: self.notesView.setFocus() self.actions['flipEditAndView'].setEnabled(viewmode) #self.actionUpAndDown.setEnabled(viewmode) self.actions['insertImage'].setEnabled(viewmode) self.noteSplitter.setSizes(splitSize) self.saveCurrentNote() # Render the note text as it is. self.notesView.updateView() def findBarVisibilityChanged(self, visible): self.actions['findText'].setChecked(visible) if visible: self.findEdit.setFocus(Qt.ShortcutFocusReason) def findText(self, back=False): flags = 0 if back: flags = QTextDocument.FindBackward if self.checkBox.isChecked(): flags = flags | QTextDocument.FindCaseSensitively text = self.findEdit.text() if not self.findMain(text, flags): if text in self.notesEdit.toPlainText(): cursor = self.notesEdit.textCursor() if back: cursor.movePosition(QTextCursor.End) else: cursor.movePosition(QTextCursor.Start) self.notesEdit.setTextCursor(cursor) self.findMain(text, flags) # self.notesView.findText(text, flags) def findMain(self, text, flags): viewFlags = QWebPage.FindFlags( flags) | QWebPage.FindWrapsAroundDocument if flags: self.notesView.findText(text, viewFlags) return self.notesEdit.find(text, flags) else: self.notesView.findText(text) return self.notesEdit.find(text) def sortLines(self): ''' sort selected lines TODO: second sort reverse the order ''' cursor = self.notesEdit.textCursor() start = cursor.selectionStart() end = cursor.selectionEnd() cursor.setPosition(start) cursor.movePosition(QTextCursor.StartOfLine) cursor.setPosition(end, mode=QTextCursor.KeepAnchor) cursor.movePosition(QTextCursor.EndOfLine, mode=QTextCursor.KeepAnchor) text = cursor.selectedText() lines = text.split('\u2029') # '\u2029' is the line break sortedLines = sorted(lines) cursor.insertText('\n'.join(sortedLines)) def notesEditInFocus(self, e): if e.gotFocus: self.actions['insertImage'].setEnabled(True) # if e.lostFocus: # self.actionInsertImage.setEnabled(False) # QWidget.focusInEvent(self,f) def searchNote(self): """ Sorting criteria: "title > path > content" Search matches are organized into html source. """ pattern = self.searchEdit.text() if not pattern: return results = [] print("Searching using", pattern) with self.ix.searcher() as searcher: matches = [] for f in ["title", "path", "content"]: queryp = QueryParser(f, self.ix.schema) queryp.add_plugin(RegexPlugin()) # r"pattern" is the desired regex term format query = queryp.parse('r"' + pattern + '"') ms = searcher.search(query, limit=None) # default limit is 10! for m in ms: if not m in matches: matches.append(m) for r in matches: title = r['title'] path = r['path'] term = r.highlights("content") results.append([title, path, term]) html = "" for title, path, hi in results: html += ("<p><a href='" + path + "'>" + title + "</a><br/><span class='path'>" + path + "</span><br/>" + hi + "</p>") self.searchView.setHtml(html) print("Finished searching", pattern) def whoosh_index(self): it = QTreeWidgetItemIterator( self.notesTree, QTreeWidgetItemIterator.All) print("Starting complete indexing.") writer = self.ix.writer() while it.value(): treeItem = it.value() name = self.notesTree.itemToPage(treeItem) path = os.path.join(self.notesTree.pageToFile(name)).replace(os.sep, '/') print(path) fileobj = open(path, 'r') content = fileobj.read() fileobj.close() writer.add_document( path=name, title=parseTitle(content, name), content=content) it += 1 writer.commit() print("Finished completely reindexing.") def listItemChanged(self, row): if row != -1: item = self.searchList.currentItem().data(Qt.UserRole) self.notesTree.setCurrentItem(item) flags = QWebPage.HighlightAllOccurrences self.notesView.findText(self.searchEdit.text(), flags) def setCurrentNote(self): item = self.notesTree.currentItem() name = self.notesTree.itemToPage(item) # Current note is inserted to head of list. notes = self.settings.recentViewedNotes() for f in notes: if f == name: notes.remove(f) notes.insert(0, name) recent_notes_n = Mikibook.settings.value('recentNotesNumber',type=int, defaultValue=20) if len(notes) > recent_notes_n: del notes[recent_notes_n:] self.settings.updateRecentViewedNotes(notes) def updateRecentViewedNotes(self): """ Switching notes will trigger this. When Alt pressed, show note number. """ self.viewedList.clear() self.viewedListActions = [] # Check notes exists. viewedNotes = self.settings.recentViewedNotes() existedNotes = [] i = 0 for f in viewedNotes: if self.notesTree.pageExists(f): existedNotes.append(f) names = f.split('/') if self.altPressed and i in range(1, 10): action = self.act(names[-1], self.openFunction(f), 'Alt+'+str(i), True, ViewedNoteIcon(i), 'Alt+'+str(i)) else: action = self.act(names[-1], self.openFunction(f), None, True) self.viewedListActions.append(action) i += 1 if not self.altPressed: self.settings.updateRecentViewedNotes(existedNotes) for action in self.viewedListActions: self.viewedList.addAction(action) if len(self.viewedListActions): self.viewedListActions[0].setChecked(True) def openFunction(self, name): item = self.notesTree.pageToItem(name) return lambda: self.notesTree.setCurrentItem(item) def raiseDock(self, widget): if not widget.isVisible(): widget.show() if widget == self.dockSearch: self.searchEdit.setFocus() widget.raise_() def flipEditAndView(self): index = self.noteSplitter.indexOf(self.notesEdit) if index == 0: self.noteSplitter.insertWidget(1, self.notesEdit) else: self.noteSplitter.insertWidget(0, self.notesEdit) def leftAndRight(self): self.liveView(True) self.noteSplitter.setOrientation(Qt.Horizontal) #self.actionLeftAndRight.setEnabled(False) #self.actionUpAndDown.setEnabled(True) def upAndDown(self): self.liveView(True) self.noteSplitter.setOrientation(Qt.Vertical) #self.actionUpAndDown.setEnabled(False) #self.actionLeftAndRight.setEnabled(True) def readmeHelp(self): readmeFile = '/usr/share/mikidown/README.mkd' if not os.path.exists(readmeFile): readmeFile = os.path.join( os.path.dirname(os.path.dirname(__file__)), 'README.mkd').replace(os.sep, '/') self.importPageCore(readmeFile) def changelogHelp(self): changeLog = "/usr/share/mikidown/Changelog.md" if not os.path.exists(changeLog): changeLog = os.path.join( os.path.dirname(os.path.dirname(__file__)), 'Changelog.md').replace(os.sep, '/') self.importPageCore(changeLog) def keyPressEvent(self, event): """ When Alt pressed, note number will be shown in viewedList. """ if event.key() == Qt.Key_Alt: self.altPressed = True self.updateRecentViewedNotes() else: QMainWindow.keyPressEvent(self, event) def keyReleaseEvent(self, event): if event.key() == Qt.Key_Alt: self.altPressed = False self.updateRecentViewedNotes() else: QMainWindow.keyPressEvent(self, event) def closeEvent(self, event): """ saveGeometry: Saves the current geometry and state for top-level widgets saveState: Restores the state of this mainwindow's toolbars and dockwidgets """ self.saveCurrentNote() self.settings.saveGeometry(self.saveGeometry()) self.settings.saveWindowState(self.saveState()) event.accept()
class Plugin(QObject): def __init__(self, iface): QObject.__init__(self) self.__iface = iface self.__shortcuts = [] self.__current_section = QComboBox() self.__current_section.setMinimumWidth(150) self.__current_graph = QComboBox() self.__current_graph.setMinimumWidth(150) self.__toolbar = None self.__axis_layer = None self.__menu = None self.__log_strati = None def initGui(self): for keyseq, slot in ( (Qt.CTRL + Qt.ALT + Qt.Key_K, self.__create_group), (Qt.CTRL + Qt.ALT + Qt.Key_S, self.__select_next_group), (Qt.CTRL + Qt.ALT + Qt.Key_N, self.__next_section), (Qt.CTRL + Qt.ALT + Qt.Key_B, self.__previous_section) ): short = QShortcut(QKeySequence(keyseq), self.__iface.mainWindow()) short.setContext(Qt.ApplicationShortcut) short.activated.connect(slot) self.__shortcuts.append(short) self.__menu = QMenu("Albion") self.__menu.aboutToShow.connect(self.__create_menu_entries) self.__iface.mainWindow().menuBar().addMenu(self.__menu) self.__toolbar = QToolBar('Albion') self.__iface.addToolBar(self.__toolbar) self.__toolbar.addAction(icon('log_strati.svg'), 'stratigraphic log').triggered.connect(self.__log_strati_clicked) self.__toolbar.addWidget(self.__current_graph) self.__current_graph.currentIndexChanged[unicode].connect(self.__current_graph_changed) self.__toolbar.addWidget(self.__current_section) self.__current_section.currentIndexChanged[unicode].connect(self.__current_section_changed) self.__toolbar.addAction(icon('previous_line.svg'), 'previous section (Ctrl+Alt+b)').triggered.connect(self.__previous_section) self.__toolbar.addAction(icon('next_line.svg'), 'next section (Ctrl+Alt+n)').triggered.connect(self.__next_section) self.__toolbar.addAction(icon('line_from_selected.svg'), 'create temporary section').triggered.connect(self.__section_from_selection) self.__viewer3d = QDockWidget('3D') self.__viewer3d.setWidget(Viewer3d()) self.__iface.addDockWidget(Qt.LeftDockWidgetArea, self.__viewer3d) self.__iface.mainWindow().tabifyDockWidget( self.__iface.mainWindow().findChild(QDockWidget, "Layers"), self.__viewer3d) self.__viewer3d_ctrl = QToolBar('3D controls') self.__viewer3d_ctrl.addWidget(ViewerControls(self.__viewer3d.widget())) self.__iface.addToolBar(self.__viewer3d_ctrl) QgsProject.instance().readProject.connect(self.__qgis__project__loaded) self.__qgis__project__loaded() # case of reload def unload(self): for s in self.__shortcuts: s.setParent(None) self.__toolbar and self.__toolbar.setParent(None) self.__menu and self.__menu.setParent(None) self.__viewer3d and self.__viewer3d.setParent(None) self.__viewer3d_ctrl and self.__viewer3d_ctrl.setParent(None) def __add_menu_entry(self, name, callback, enabled=True, help_str=''): act = self.__menu.addAction(name) if callback is not None: act.triggered.connect(callback) act.setEnabled(enabled) act.setToolTip(help_str) else: act.setEnabled(False) act.setToolTip("NOT INMPLEMENTED "+help_str) return act def __create_menu_entries(self): self.__menu.clear() self.__add_menu_entry('New &Project', self.__new_project) self.__add_menu_entry('Import Project', self.__import_project) self.__add_menu_entry('Upgrade Project', self.__upgrade_project) self.__menu.addSeparator() self.__add_menu_entry('&Import Data', self.__import_data, self.project is not None, "Import data from directory. The data files are in ") self.__menu.addSeparator() self.__add_menu_entry('Create cells', self.__create_cells, self.project is not None and self.project.has_collar, "Create Delaunay triangulation of collar layer.") self.__add_menu_entry('Refresh all edges', self.__refresh_all_edge, self.project is not None and self.project.has_cell, "Refresh materialized view of all cell edges used by graph possible edges.") self.__menu.addSeparator() #self.__add_menu_entry(u'Create section views 0° and 90°', self.__create_section_view_0_90, # False and self.project is not None and self.project.has_hole, # "Create section views (i.e. cut directions) to work West-East and South-North for this project") #self.__add_menu_entry(u'Create section views -45° and 45°', None, # False and self.project is not None and self.project.has_hole, # "Create section views (i.e. cut directions) to work SE-NW and SW-NE for this project") # #self.__menu.addSeparator() self.__add_menu_entry('Create sections', self.__create_sections, self.project is not None and self.project.has_group_cell, "Once cell groups have been defined, create section lines.") self.__menu.addSeparator() self.__add_menu_entry('Compute &Mineralization', self.__compute_mineralization, self.project is not None and self.project.has_radiometry, "") self.__menu.addSeparator() self.__add_menu_entry('New &Graph', self.__new_graph, self.project is not None, "Create a new grap.h") self.__add_menu_entry('Delete Graph', self.__delete_graph, self.project is not None) self.__menu.addSeparator() self.__add_menu_entry('Create volumes', self.__create_volumes, self.project is not None and bool(self.__current_graph.currentText()), "Create volumes associated with current graph.") self.__menu.addSeparator() self.__add_menu_entry('Create terminations', self.__create_terminations, self.project is not None and bool(self.__current_graph.currentText()), "Create terminations associated with current graph.") self.__menu.addSeparator() self.__add_menu_entry('Toggle axis', self.__toggle_axis) self.__menu.addSeparator() self.__add_menu_entry('Export Project', self.__export_project, self.project is not None) self.__add_menu_entry('Export Sections', None, self.project is not None and self.project.has_section, "Export triangulated section in .obj or .dxf format") self.__add_menu_entry('Export Volume', self.__export_volume, self.project is not None and bool(self.__current_graph.currentText()), "Export volume of current graph in .obj or .dxf format") self.__menu.addSeparator() self.__menu.addAction('Help').triggered.connect(self.open_help) def __current_graph_changed(self, graph_id): if self.project is None: return self.__viewer3d.widget().set_graph(graph_id) def __getattr__(self, name): if name == "project": project_name = QgsProject.instance().readEntry("albion", "project_name", "")[0] return Project(project_name) if project_name else None else: raise AttributeError(name) def __refresh_all_edge(self): if self.project is None: return self.project.refresh_all_edge() def __create_terminations(self): if self.project is None: return self.project.create_terminations(self.__current_graph.currentText()) self.__viewer3d.widget().refresh_data() self.__refresh_layers('section') def __create_volumes(self): if self.project is None: return self.project.create_volumes(self.__current_graph.currentText()) self.__viewer3d.widget().refresh_data() def __next_section(self): if self.project is None: return self.project.next_section(self.__current_section.currentText()) self.__refresh_layers('section') self.__viewer3d.widget().scene.update('section') self.__viewer3d.widget().update() def __previous_section(self): if self.project is None: return self.project.previous_section(self.__current_section.currentText()) self.__refresh_layers('section') self.__viewer3d.widget().scene.update('section') self.__viewer3d.widget().update() def __refresh_layers(self, name=None): for layer in self.__iface.mapCanvas().layers(): if name is None or layer.name().find(name) != -1: layer.triggerRepaint() def __current_section_changed(self, section_id): layers = QgsMapLayerRegistry.instance().mapLayersByName(u"group_cell") if len(layers): layers[0].setSubsetString("section_id='{}'".format(section_id)) self.__refresh_layers('section') def __select_next_group(self): if self.project and self.__iface.activeLayer() and self.__iface.activeLayer().name() == u"cell": self.__iface.activeLayer().removeSelection() self.__iface.activeLayer().selectByExpression( "id in ({})".format(",".join(project.next_group_ids()))) def __create_group(self): if self.project and self.__iface.activeLayer() and self.__iface.activeLayer().name() == u"cell": if self.__iface.activeLayer().selectedFeatureCount(): section = self.__current_section.currentText() self.project.create_group(section, [f['id'] for f in self.__iface.activeLayer().selectedFeatures()]) self.__iface.activeLayer().removeSelection() self.__refresh_layers('group_cell') def __qgis__project__loaded(self): if self.project is None: return self.__current_graph.clear() self.__current_section.clear() self.__current_section.addItems(self.project.sections()) self.__current_graph.addItems(self.project.graphs()) layers = QgsMapLayerRegistry.instance().mapLayersByName('section.anchor') if len(layers): layers[0].editingStopped.connect(self.__update_section_list) self.__viewer3d.widget().resetScene(self.project) def __update_section_list(self): self.__current_section.clear() self.__current_section.addItems(self.project.sections()) def __upgrade_project(self): project_name, ok = QInputDialog.getText(self.__iface.mainWindow(), "Database name", "Database name:", QLineEdit.Normal, '') if not ok: return Project(project_name).update() def __new_project(self): # @todo open dialog to configure project name and srid fil = QFileDialog.getSaveFileName(None, u"New project name (no space, plain ascii)", QgsProject.instance().readEntry("albion", "last_dir", "")[0], "QGIS poject file (*.qgs)") if not fil: return fil = fil if len(fil)>4 and fil[-4:]=='.qgs' else fil+'.qgs' fil = fil.replace(' ','_') try: fil.decode('ascii') except UnicodeDecodeError: self.__iface.messageBar().pushError('Albion:', "project name may only contain asci character (no accent)") return srid, ok = QInputDialog.getText(self.__iface.mainWindow(), "Project SRID", "Project SRID EPSG:", QLineEdit.Normal, '32632') if not ok: return srid = int(srid) project_name = str(os.path.split(fil)[1][:-4]) if Project.exists(project_name): if QMessageBox.Yes != QMessageBox(QMessageBox.Information, "Delete existing DB", "Database {} exits, to you want to delete it ?".format(project_name), QMessageBox.Yes|QMessageBox.No).exec_(): return Project.delete(project_name) self.__iface.messageBar().pushInfo('Albion:', "creating project...") Project.create(project_name, srid) # load template open(fil, 'w').write( open(resource('template_project.qgs')).read().replace('template_project', project_name)) self.__iface.newProject() QgsProject.instance().setFileName(fil) QgsProject.instance().read() QgsProject.instance().writeEntry("albion", "project_name", project_name) QgsProject.instance().writeEntry("albion", "srid", srid) QgsProject.instance().write() self.__qgis__project__loaded() def __import_data(self): if self.project is None: return if not QgsProject.instance().readEntry("albion", "conn_info", "")[0]: return dir_ = QFileDialog.getExistingDirectory(None, u"Data directory", QgsProject.instance().readEntry("albion", "last_dir", "")[0]) if not dir_: return QgsProject.instance().writeEntry("albion", "last_dir", dir_), progressMessageBar = self.__iface.messageBar().createMessage("Loading {}...".format(dir_)) progress = QProgressBar() progress.setAlignment(Qt.AlignLeft|Qt.AlignVCenter) progressMessageBar.layout().addWidget(progress) self.__iface.messageBar().pushWidget(progressMessageBar, self.__iface.messageBar().INFO) self.project.import_data(dir_, ProgressBar(progress)) self.project.triangulate() self.project.create_section_view_0_90(4) self.__iface.messageBar().clearWidgets() collar = QgsMapLayerRegistry.instance().mapLayersByName('collar')[0] collar.reload() collar.updateExtents() self.__iface.setActiveLayer(collar) QApplication.instance().processEvents() while self.__iface.mapCanvas().isDrawing(): QApplication.instance().processEvents() self.__iface.zoomToActiveLayer() self.__iface.actionSaveProject().trigger() self.__viewer3d.widget().resetScene(self.project) self.__current_section.clear() self.__current_section.addItems(self.project.sections()) def __new_graph(self): if self.project is None: return graph, ok = QInputDialog.getText(self.__iface.mainWindow(), "Graph", "Graph name:", QLineEdit.Normal, 'test_graph') if not ok: return parent, ok = QInputDialog.getText(self.__iface.mainWindow(), "Parent Graph", "Parent Graph name:", QLineEdit.Normal, '') if not ok: return self.project.new_graph(graph, parent) self.__current_graph.addItem(graph) self.__current_graph.setCurrentIndex(self.__current_graph.findText(graph)) def __delete_graph(self): if self.project is None: return graph, ok = QInputDialog.getText(self.__iface.mainWindow(), "Graph", "Graph name:", QLineEdit.Normal, self.__current_graph.currentText()) if not ok: return self.__current_graph.removeItem(self.__current_graph.findText(graph)) def __toggle_axis(self): if self.__axis_layer: pass QgsMapLayerRegistry.instance().removeMapLayer(self.__axis_layer.id()) self.__axis_layer = None else: self.__axis_layer = AxisLayer(self.__iface.mapCanvas().mapSettings().destinationCrs()) QgsMapLayerRegistry.instance().addMapLayer(self.__axis_layer) self.__refresh_layers() def __create_cells(self): if self.project is None: return self.project.triangulate() self.__refresh_layers('cells') def __create_sections(self): if self.project is None: return self.project.create_sections() def __compute_mineralization(self): MineralizationDialog(self.project).exec_() def __export_volume(self): if self.project is None: return fil = QFileDialog.getSaveFileName(None, u"Export volume for current graph", QgsProject.instance().readEntry("albion", "last_dir", "")[0], "File formats (*.dxf *.obj)") if not fil: return QgsProject.instance().writeEntry("albion", "last_dir", os.path.dirname(fil)), if fil[-4:] == '.obj': self.project.export_obj(self.__current_graph.currentText(), fil) elif fil[-4:] == '.dxf': self.project.export_dxf(self.__current_graph.currentText(), fil) else: self.__iface.messageBar().pushWarning('Albion', 'unsupported extension for volume export') def __import_project(self): fil = QFileDialog.getOpenFileName(None, u"Import project from file", QgsProject.instance().readEntry("albion", "last_dir", "")[0], "File formats (*.zip)") if not fil: return QgsProject.instance().writeEntry("albion", "last_dir", os.path.dirname(fil)), if fil[-4:] != '.zip': self.__iface.messageBar().pushWarning('Albion', 'unsupported extension for import') project_name = os.path.split(fil)[1][:-4] dir_ = tempfile.gettempdir() with zipfile.ZipFile(fil, "r") as z: z.extractall(dir_) dump = find_in_dir(dir_, '.dump') prj = find_in_dir(dir_, '.qgs') self.__iface.messageBar().pushInfo('Albion', 'loading {} from {}'.format(project_name, dump)) if Project.exists(project_name): if QMessageBox.Yes != QMessageBox(QMessageBox.Information, "Delete existing DB", "Database {} exits, to you want to delete it ?".format(project_name), QMessageBox.Yes|QMessageBox.No).exec_(): return Project.delete(project_name) project = Project.import_(project_name, dump) QgsProject.instance().read(QFileInfo(prj)) def __export_project(self): if self.project is None: return fil = QFileDialog.getSaveFileName(None, u"Export project", QgsProject.instance().readEntry("albion", "last_dir", "")[0], "Data files(*.zip)") if not fil: return QgsProject.instance().writeEntry("albion", "last_dir", os.path.dirname(fil)), if os.path.exists(fil): os.remove(fil) with zipfile.ZipFile(fil, 'w') as project: dump = tempfile.mkstemp()[1] self.project.export(dump) project.write(dump, self.project.name+'.dump') project.write(QgsProject.instance().fileName(), os.path.split(QgsProject.instance().fileName())[1]) def __create_section_view_0_90(self): if self.project is None: return self.project.create_section_view_0_90() def __log_strati_clicked(self): #@todo switch behavior when in section view -> ortho self.__click_tool = QgsMapToolEmitPoint(self.__iface.mapCanvas()) self.__iface.mapCanvas().setMapTool(self.__click_tool) self.__click_tool.canvasClicked.connect(self.__map_log_clicked) def __map_log_clicked(self, point, button): self.__click_tool.setParent(None) self.__click_tool = None if self.project is None: self.__log_strati and self.__log_strati.setParent(None) self.__log_strati = None return if self.__log_strati is None: self.__log_strati = QDockWidget('Stratigraphic Log') self.__log_strati.setWidget(BoreHoleWindow(self.project)) self.__iface.addDockWidget(Qt.LeftDockWidgetArea, self.__log_strati) self.__iface.mainWindow().tabifyDockWidget( self.__iface.mainWindow().findChild(QDockWidget, "Layers"), self.__log_strati) res = self.project.closest_hole_id(point.x(), point.y()) if res: self.__log_strati.widget().scene.set_current_id(res) self.__log_strati.show() self.__log_strati.raise_() def __section_from_selection(self): if self.project is None: return if self.__iface.activeLayer() and self.__iface.activeLayer().name() == u"collar" \ and self.__iface.activeLayer().selectedFeatures(): collar = self.__iface.activeLayer() selection = collar.selectedFeatures() if len(selection) < 2: return def align(l): assert len(l) >= 2 res = numpy.array(l[:2]) for p in l[2:]: u, v = res[0] - res[1], p - res[1] if numpy.dot(u,v) < 0: res[1] = p elif numpy.dot(u, u) < numpy.dot(v,v): res[0] = p # align with ref direction sqrt2 = math.sqrt(2.)/2 l = l[numpy.argsort(numpy.dot(l-res[0], res[1]-res[0]))] d = numpy.array(l[-1] - l[0]) dr = numpy.array([(0,1),(sqrt2, sqrt2),(1,0), (sqrt2, -sqrt2)]) i = numpy.argmax(numpy.abs(dr.dot(d))) return l if (dr.dot(d))[i] > 0 else l[::-1] line = LineString(align(numpy.array([f.geometry().asPoint() for f in selection]))) collar.removeSelection() self.project.set_section_geom(self.__current_section.currentText(), line) self.__refresh_layers('section') self.__viewer3d.widget().scene.update('section') self.__viewer3d.widget().update() def open_help(self): QDesktopServices.openUrl(QUrl.fromLocalFile(os.path.join(os.path.dirname(__file__), 'doc', 'build', 'html', 'index.html')))
class ViewerWnd(QMainWindow): def __init__(self, app, dictOpts): QMainWindow.__init__(self) self.setWindowTitle("PostGIS Layer Viewer - v.1.6.1") self.setTabPosition(Qt.BottomDockWidgetArea, QTabWidget.North) self.canvas = QgsMapCanvas() self.canvas.setCanvasColor(Qt.white) self.canvas.useImageToRender(True) self.canvas.enableAntiAliasing(True) self.setCentralWidget(self.canvas) actionZoomIn = QAction(QIcon(imgs_dir + "mActionZoomIn.png"), QString("Zoom in"), self) actionZoomOut = QAction(QIcon(imgs_dir + "mActionZoomOut.png"), QString("Zoom out"), self) actionPan = QAction(QIcon(imgs_dir + "mActionPan.png"), QString("Pan"), self) actionZoomFullExtent = QAction( QIcon(imgs_dir + "mActionZoomFullExtent.png"), QString("Zoom full"), self) actionZoomIn.setCheckable(True) actionZoomOut.setCheckable(True) actionPan.setCheckable(True) self.connect(actionZoomIn, SIGNAL("triggered()"), self.zoomIn) self.connect(actionZoomOut, SIGNAL("triggered()"), self.zoomOut) self.connect(actionPan, SIGNAL("triggered()"), self.pan) self.connect(actionZoomFullExtent, SIGNAL("triggered()"), self.zoomFullExtent) self.actionGroup = QActionGroup(self) self.actionGroup.addAction(actionPan) self.actionGroup.addAction(actionZoomIn) self.actionGroup.addAction(actionZoomOut) # Create the toolbar self.toolbar = self.addToolBar("Map tools") self.toolbar.addAction(actionPan) self.toolbar.addAction(actionZoomIn) self.toolbar.addAction(actionZoomOut) self.toolbar.addAction(actionZoomFullExtent) # Create the map tools self.toolPan = QgsMapToolPan(self.canvas) self.toolPan.setAction(actionPan) self.toolZoomIn = QgsMapToolZoom(self.canvas, False) # false = in self.toolZoomIn.setAction(actionZoomIn) self.toolZoomOut = QgsMapToolZoom(self.canvas, True) # true = out self.toolZoomOut.setAction(actionZoomOut) # Create the statusbar self.statusbar = QStatusBar(self) self.statusbar.setObjectName("statusbar") self.setStatusBar(self.statusbar) self.lblXY = QLabel() self.lblXY.setFrameStyle(QFrame.Box) self.lblXY.setMinimumWidth(170) self.lblXY.setAlignment(Qt.AlignCenter) self.statusbar.setSizeGripEnabled(False) self.statusbar.addPermanentWidget(self.lblXY, 0) self.lblScale = QLabel() self.lblScale.setFrameStyle(QFrame.StyledPanel) self.lblScale.setMinimumWidth(140) self.statusbar.addPermanentWidget(self.lblScale, 0) self.createLegendWidget() # Create the legend widget self.connect(app, SIGNAL("loadPgLayer"), self.loadLayer) self.connect(self.canvas, SIGNAL("scaleChanged(double)"), self.changeScale) self.connect(self.canvas, SIGNAL("xyCoordinates(const QgsPoint&)"), self.updateXY) self.pan() # Default self.plugins = Plugins(self, self.canvas, dictOpts['-h'], dictOpts['-p'], dictOpts['-d'], dictOpts['-U'], dictOpts['-W']) self.createAboutWidget() self.layerSRID = '-1' self.loadLayer(dictOpts) def zoomIn(self): self.canvas.setMapTool(self.toolZoomIn) def zoomOut(self): self.canvas.setMapTool(self.toolZoomOut) def pan(self): self.canvas.setMapTool(self.toolPan) def zoomFullExtent(self): self.canvas.zoomToFullExtent() def about(self): pass def createLegendWidget(self): """ Create the map legend widget and associate it to the canvas """ self.legend = Legend(self) self.legend.setCanvas(self.canvas) self.legend.setObjectName("theMapLegend") self.LegendDock = QDockWidget("Layers", self) self.LegendDock.setObjectName("legend") self.LegendDock.setTitleBarWidget(QWidget()) self.LegendDock.setWidget(self.legend) self.LegendDock.setContentsMargins(0, 0, 0, 0) self.addDockWidget(Qt.BottomDockWidgetArea, self.LegendDock) def createAboutWidget(self): self.AboutDock = QDockWidget("About", self) self.AboutDock.setObjectName("about") self.AboutDock.setTitleBarWidget(QWidget()) self.AboutDock.setContentsMargins(0, 0, 0, 0) self.tabifyDockWidget(self.LegendDock, self.AboutDock) self.LegendDock.raise_() # legendDock at the top from PyQt4.QtCore import QRect from PyQt4.QtGui import QSizePolicy, QGridLayout, QFont font = QFont() font.setFamily("Sans Serif") font.setPointSize(8.7) self.AboutWidget = QWidget() self.AboutWidget.setFont(font) self.AboutWidget.setObjectName("AboutWidget") self.AboutDock.setWidget(self.AboutWidget) self.labelAbout = QLabel(self.AboutWidget) self.labelAbout.setAlignment(Qt.AlignCenter) self.labelAbout.setWordWrap(True) self.gridLayout = QGridLayout(self.AboutWidget) self.gridLayout.setContentsMargins(0, 0, 0, 0) self.gridLayout.setObjectName("gridLayout") self.gridLayout.addWidget(self.labelAbout, 0, 1, 1, 1) self.labelAbout.setTextInteractionFlags(Qt.LinksAccessibleByMouse | Qt.LinksAccessibleByKeyboard | Qt.TextSelectableByKeyboard | Qt.TextSelectableByMouse) self.labelAbout.setOpenExternalLinks(True) self.labelAbout.setText("<html><head/><body><a href=\"http://geotux.tuxfamily.org/index.php/en/geo-blogs/item/293-consola-sql-para-plugin-pgadmin-postgis-viewer\">PostGIS Layer Viewer</a> v.1.6.1 (2015.02.24)<br \><br \>" \ "Copyright (c) 2010 Ivan Mincik,<br \>[email protected]<br \>" \ u"Copyright (c) 2011-2015 Germán Carrillo,<br \>[email protected]<br \><br \>" \ "<i>Licensed under the terms of GNU GPL v.2.0</i><br \><br \>" \ "Based on PyQGIS. Plugin Fast SQL Layer by Pablo T. Carreira.</body></html>" ) def loadLayer(self, dictOpts): print 'I: Loading the layer...' self.layerSRID = dictOpts[ 'srid'] # To access the SRID when querying layer properties if not self.isActiveWindow(): self.activateWindow() self.raise_() if dictOpts['type'] == 'vector': # QGIS connection uri = QgsDataSourceURI() uri.setConnection(dictOpts['-h'], dictOpts['-p'], dictOpts['-d'], dictOpts['-U'], dictOpts['-W']) uri.setDataSource(dictOpts['-s'], dictOpts['-t'], dictOpts['-g']) layer = QgsVectorLayer(uri.uri(), dictOpts['-s'] + '.' + dictOpts['-t'], "postgres") elif dictOpts['type'] == 'raster': connString = "PG: dbname=%s host=%s user=%s password=%s port=%s mode=2 " \ "schema=%s column=%s table=%s" % ( dictOpts['-d'], dictOpts['-h'], dictOpts['-U'], dictOpts['-W'], dictOpts['-p'], dictOpts['-s'], dictOpts['col'], dictOpts['-t'] ) layer = QgsRasterLayer(connString, dictOpts['-s'] + '.' + dictOpts['-t']) if layer.isValid(): layer.setContrastEnhancement( QgsContrastEnhancement.StretchToMinimumMaximum) self.addLayer(layer, self.layerSRID) def addLayer(self, layer, srid='-1'): if layer.isValid(): # Only in case that srid != -1, read the layer SRS properties, otherwise don't since it will return 4326 if srid != '-1': self.layerSRID = layer.crs().description() + ' (' + str( layer.crs().postgisSrid()) + ')' else: self.layerSRID = 'Unknown SRS (-1)' if self.canvas.layerCount() == 0: self.canvas.setExtent(layer.extent()) if srid != '-1': print 'I: Map SRS (EPSG): %s' % self.layerSRID self.canvas.setMapUnits(layer.crs().mapUnits()) else: print 'I: Unknown Reference System' self.canvas.setMapUnits(0) # 0: QGis.Meters return QgsMapLayerRegistry.instance().addMapLayer(layer) return False def activeLayer(self): """ Returns the active layer in the layer list widget """ return self.legend.activeLayer() def getLayerProperties(self, l): """ Create a layer-properties string (l:layer)""" print 'I: Generating layer properties...' if l.type() == 0: # Vector wkbType = [ "WKBUnknown", "WKBPoint", "WKBLineString", "WKBPolygon", "WKBMultiPoint", "WKBMultiLineString", "WKBMultiPolygon", "WKBNoGeometry", "WKBPoint25D", "WKBLineString25D", "WKBPolygon25D", "WKBMultiPoint25D", "WKBMultiLineString25D", "WKBMultiPolygon25D" ] properties = "Source: %s\n" \ "Geometry type: %s\n" \ "Number of features: %s\n" \ "Number of fields: %s\n" \ "SRS (EPSG): %s\n" \ "Extent: %s " \ % ( l.source(), wkbType[l.wkbType()], l.featureCount(), l.dataProvider().fields().count(), self.layerSRID, l.extent().toString() ) elif l.type() == 1: # Raster rType = [ "GrayOrUndefined (single band)", "Palette (single band)", "Multiband", "ColorLayer" ] properties = "Source: %s\n" \ "Raster type: %s\n" \ "Width-Height (pixels): %sx%s\n" \ "Bands: %s\n" \ "SRS (EPSG): %s\n" \ "Extent: %s" \ % ( l.source(), rType[l.rasterType()], l.width(), l.height(), l.bandCount(), self.layerSRID, l.extent().toString() ) self.layerSRID = '-1' # Initialize the srid return properties def changeScale(self, scale): self.lblScale.setText("Scale 1:" + formatNumber(scale)) def updateXY(self, p): if self.canvas.mapUnits() == 2: # Degrees self.lblXY.setText( formatToDegrees( p.x() ) + " | " \ + formatToDegrees( p.y() ) ) else: # Unidad lineal self.lblXY.setText( formatNumber( p.x() ) + " | " \ + formatNumber( p.y() ) + "" )
class ViewerWnd( QMainWindow ): def __init__( self, app, dictOpts ): QMainWindow.__init__( self ) self.setWindowTitle( "PostGIS Layer Viewer - v.1.6.1" ) self.setTabPosition( Qt.BottomDockWidgetArea, QTabWidget.North ) self.canvas = QgsMapCanvas() self.canvas.setCanvasColor( Qt.white ) self.canvas.useImageToRender( True ) self.canvas.enableAntiAliasing( True ) self.setCentralWidget( self.canvas ) actionZoomIn = QAction( QIcon( imgs_dir + "mActionZoomIn.png" ), QString( "Zoom in" ), self ) actionZoomOut = QAction( QIcon( imgs_dir + "mActionZoomOut.png" ), QString( "Zoom out" ), self ) actionPan = QAction( QIcon( imgs_dir + "mActionPan.png" ), QString( "Pan" ), self ) actionZoomFullExtent = QAction( QIcon( imgs_dir + "mActionZoomFullExtent.png" ), QString( "Zoom full" ), self ) actionZoomIn.setCheckable( True ) actionZoomOut.setCheckable( True ) actionPan.setCheckable( True ) self.connect(actionZoomIn, SIGNAL( "triggered()" ), self.zoomIn ) self.connect(actionZoomOut, SIGNAL( "triggered()" ), self.zoomOut ) self.connect(actionPan, SIGNAL( "triggered()" ), self.pan ) self.connect(actionZoomFullExtent, SIGNAL( "triggered()" ), self.zoomFullExtent ) self.actionGroup = QActionGroup( self ) self.actionGroup.addAction( actionPan ) self.actionGroup.addAction( actionZoomIn ) self.actionGroup.addAction( actionZoomOut ) # Create the toolbar self.toolbar = self.addToolBar( "Map tools" ) self.toolbar.addAction( actionPan ) self.toolbar.addAction( actionZoomIn ) self.toolbar.addAction( actionZoomOut ) self.toolbar.addAction( actionZoomFullExtent ) # Create the map tools self.toolPan = QgsMapToolPan( self.canvas ) self.toolPan.setAction( actionPan ) self.toolZoomIn = QgsMapToolZoom( self.canvas, False ) # false = in self.toolZoomIn.setAction( actionZoomIn ) self.toolZoomOut = QgsMapToolZoom( self.canvas, True ) # true = out self.toolZoomOut.setAction( actionZoomOut ) # Create the statusbar self.statusbar = QStatusBar( self ) self.statusbar.setObjectName( "statusbar" ) self.setStatusBar( self.statusbar ) self.lblXY = QLabel() self.lblXY.setFrameStyle( QFrame.Box ) self.lblXY.setMinimumWidth( 170 ) self.lblXY.setAlignment( Qt.AlignCenter ) self.statusbar.setSizeGripEnabled( False ) self.statusbar.addPermanentWidget( self.lblXY, 0 ) self.lblScale = QLabel() self.lblScale.setFrameStyle( QFrame.StyledPanel ) self.lblScale.setMinimumWidth( 140 ) self.statusbar.addPermanentWidget( self.lblScale, 0 ) self.createLegendWidget() # Create the legend widget self.connect( app, SIGNAL( "loadPgLayer" ), self.loadLayer ) self.connect( self.canvas, SIGNAL( "scaleChanged(double)" ), self.changeScale ) self.connect( self.canvas, SIGNAL( "xyCoordinates(const QgsPoint&)" ), self.updateXY ) self.pan() # Default self.plugins = Plugins( self, self.canvas, dictOpts['-h'], dictOpts['-p'], dictOpts['-d'], dictOpts['-U'], dictOpts['-W'] ) self.createAboutWidget() self.layerSRID = '-1' self.loadLayer( dictOpts ) def zoomIn( self ): self.canvas.setMapTool( self.toolZoomIn ) def zoomOut( self ): self.canvas.setMapTool( self.toolZoomOut ) def pan( self ): self.canvas.setMapTool( self.toolPan ) def zoomFullExtent( self ): self.canvas.zoomToFullExtent() def about( self ): pass def createLegendWidget( self ): """ Create the map legend widget and associate it to the canvas """ self.legend = Legend( self ) self.legend.setCanvas( self.canvas ) self.legend.setObjectName( "theMapLegend" ) self.LegendDock = QDockWidget( "Layers", self ) self.LegendDock.setObjectName( "legend" ) self.LegendDock.setTitleBarWidget( QWidget() ) self.LegendDock.setWidget( self.legend ) self.LegendDock.setContentsMargins ( 0, 0, 0, 0 ) self.addDockWidget( Qt.BottomDockWidgetArea, self.LegendDock ) def createAboutWidget( self ): self.AboutDock = QDockWidget( "About", self ) self.AboutDock.setObjectName( "about" ) self.AboutDock.setTitleBarWidget( QWidget() ) self.AboutDock.setContentsMargins( 0, 0, 0, 0 ) self.tabifyDockWidget( self.LegendDock, self.AboutDock ) self.LegendDock.raise_() # legendDock at the top from PyQt4.QtCore import QRect from PyQt4.QtGui import QSizePolicy, QGridLayout, QFont font = QFont() font.setFamily("Sans Serif") font.setPointSize(8.7) self.AboutWidget = QWidget() self.AboutWidget.setFont( font ) self.AboutWidget.setObjectName("AboutWidget") self.AboutDock.setWidget( self.AboutWidget ) self.labelAbout = QLabel( self.AboutWidget ) self.labelAbout.setAlignment(Qt.AlignCenter) self.labelAbout.setWordWrap(True) self.gridLayout = QGridLayout(self.AboutWidget) self.gridLayout.setContentsMargins(0, 0, 0, 0) self.gridLayout.setObjectName("gridLayout") self.gridLayout.addWidget(self.labelAbout, 0, 1, 1, 1) self.labelAbout.setTextInteractionFlags(Qt.LinksAccessibleByMouse|Qt.LinksAccessibleByKeyboard|Qt.TextSelectableByKeyboard|Qt.TextSelectableByMouse) self.labelAbout.setOpenExternalLinks( True ) self.labelAbout.setText("<html><head/><body><a href=\"http://geotux.tuxfamily.org/index.php/en/geo-blogs/item/293-consola-sql-para-plugin-pgadmin-postgis-viewer\">PostGIS Layer Viewer</a> v.1.6.1 (2015.02.24)<br \><br \>" \ "Copyright (c) 2010 Ivan Mincik,<br \>[email protected]<br \>" \ u"Copyright (c) 2011-2015 Germán Carrillo,<br \>[email protected]<br \><br \>" \ "<i>Licensed under the terms of GNU GPL v.2.0</i><br \><br \>" \ "Based on PyQGIS. Plugin Fast SQL Layer by Pablo T. Carreira.</body></html>" ) def loadLayer( self, dictOpts ): print 'I: Loading the layer...' self.layerSRID = dictOpts[ 'srid' ] # To access the SRID when querying layer properties if not self.isActiveWindow(): self.activateWindow() self.raise_() if dictOpts['type'] == 'vector': # QGIS connection uri = QgsDataSourceURI() uri.setConnection( dictOpts['-h'], dictOpts['-p'], dictOpts['-d'], dictOpts['-U'], dictOpts['-W'] ) uri.setDataSource( dictOpts['-s'], dictOpts['-t'], dictOpts['-g'] ) layer = QgsVectorLayer( uri.uri(), dictOpts['-s'] + '.' + dictOpts['-t'], "postgres" ) elif dictOpts['type'] == 'raster': connString = "PG: dbname=%s host=%s user=%s password=%s port=%s mode=2 " \ "schema=%s column=%s table=%s" % ( dictOpts['-d'], dictOpts['-h'], dictOpts['-U'], dictOpts['-W'], dictOpts['-p'], dictOpts['-s'], dictOpts['col'], dictOpts['-t'] ) layer = QgsRasterLayer( connString, dictOpts['-s'] + '.' + dictOpts['-t'] ) if layer.isValid(): layer.setContrastEnhancement( QgsContrastEnhancement.StretchToMinimumMaximum ) self.addLayer( layer, self.layerSRID ) def addLayer( self, layer, srid='-1' ): if layer.isValid(): # Only in case that srid != -1, read the layer SRS properties, otherwise don't since it will return 4326 if srid != '-1': self.layerSRID = layer.crs().description() + ' (' + str( layer.crs().postgisSrid() ) + ')' else: self.layerSRID = 'Unknown SRS (-1)' if self.canvas.layerCount() == 0: self.canvas.setExtent( layer.extent() ) if srid != '-1': print 'I: Map SRS (EPSG): %s' % self.layerSRID self.canvas.setMapUnits( layer.crs().mapUnits() ) else: print 'I: Unknown Reference System' self.canvas.setMapUnits( 0 ) # 0: QGis.Meters return QgsMapLayerRegistry.instance().addMapLayer( layer ) return False def activeLayer( self ): """ Returns the active layer in the layer list widget """ return self.legend.activeLayer() def getLayerProperties( self, l ): """ Create a layer-properties string (l:layer)""" print 'I: Generating layer properties...' if l.type() == 0: # Vector wkbType = ["WKBUnknown","WKBPoint","WKBLineString","WKBPolygon", "WKBMultiPoint","WKBMultiLineString","WKBMultiPolygon", "WKBNoGeometry","WKBPoint25D","WKBLineString25D","WKBPolygon25D", "WKBMultiPoint25D","WKBMultiLineString25D","WKBMultiPolygon25D"] properties = "Source: %s\n" \ "Geometry type: %s\n" \ "Number of features: %s\n" \ "Number of fields: %s\n" \ "SRS (EPSG): %s\n" \ "Extent: %s " \ % ( l.source(), wkbType[l.wkbType()], l.featureCount(), l.dataProvider().fields().count(), self.layerSRID, l.extent().toString() ) elif l.type() == 1: # Raster rType = [ "GrayOrUndefined (single band)", "Palette (single band)", "Multiband", "ColorLayer" ] properties = "Source: %s\n" \ "Raster type: %s\n" \ "Width-Height (pixels): %sx%s\n" \ "Bands: %s\n" \ "SRS (EPSG): %s\n" \ "Extent: %s" \ % ( l.source(), rType[l.rasterType()], l.width(), l.height(), l.bandCount(), self.layerSRID, l.extent().toString() ) self.layerSRID = '-1' # Initialize the srid return properties def changeScale( self, scale ): self.lblScale.setText( "Scale 1:" + formatNumber( scale ) ) def updateXY( self, p ): if self.canvas.mapUnits() == 2: # Degrees self.lblXY.setText( formatToDegrees( p.x() ) + " | " \ + formatToDegrees( p.y() ) ) else: # Unidad lineal self.lblXY.setText( formatNumber( p.x() ) + " | " \ + formatNumber( p.y() ) + "" )
def lauchGUI(self, WorkSpace, aCase, sobjXML, Args): """ mw.dockWidgetBrowser is the Browser of the CFD MainView """ log.debug("lauchGUI") from cs_gui import process_cmd_line if CFD_Code() == CFD_Saturne: from cs_package import package from code_saturne.Base.MainView import MainView elif CFD_Code() == CFD_Neptune: from nc_package import package from neptune_cfd.core.MainView import MainView if sobjXML == None: Title = "unnamed" else: Title = sobjXML.GetName() self.Workspace = WorkSpace pkg = package() case, splash = process_cmd_line(Args) mw = MainView(pkg, case, aCase) # Put the standard panel of the MainView inside a QDockWidget # in the SALOME Desktop aTitle = self.setWindowTitle_CFD(mw, aCase, Title) dsk = sgPyQt.getDesktop() dock = QDockWidget(aTitle) dock.setWidget(mw.frame) dock.setMinimumWidth(520) dsk.addDockWidget(Qt.RightDockWidgetArea, dock) dock.setVisible(True) dock.show() # Put the QTreeView of the MainView which is already inside a QDockWidget # in the SALOME Desktop BrowserTitle = aTitle + " Browser" mw.dockWidgetBrowser.setWindowTitle(BrowserTitle) dsk.addDockWidget(Qt.LeftDockWidgetArea, mw.dockWidgetBrowser) mw.dockWidgetBrowser.setVisible(True) mw.dockWidgetBrowser.show() mw.dockWidgetBrowser.raise_() dock.raise_() #Add Dock windows are managed by CFDGUI_Management class studyId = sgPyQt.getStudyId() aStudyCFD = aCase.GetFather() aCaseCFD = aCase xmlFileName = str(Title) _c_CFDGUI.set_d_CfdCases(studyId, dock, mw.dockWidgetBrowser, mw, aStudyCFD, aCaseCFD, xmlFileName, sobjXML) self.connect(dock, SIGNAL("visibilityChanged(bool)"), self.setdockWindowBrowserActivated) self.connect(mw.dockWidgetBrowser, SIGNAL("visibilityChanged(bool)"), self.setdockWindowActivated) self.connect(dock.toggleViewAction(), SIGNAL("toggled(bool)"), self.setdockWB) self.connect(mw.dockWidgetBrowser.toggleViewAction(), SIGNAL("toggled(bool)"), self.setdock) _c_CFDGUI.tabifyDockWindows(dsk, studyId) self.showDockWindows(studyId, xmlFileName, aCaseCFD.GetName(), aStudyCFD.GetName()) updateObjectBrowser() return mw