""" qtgui/MGWebBrowser.py: CCP4MG Molecular Graphics Program Copyright (C) 2001-2008 University of York, CCLRC Copyright (C) 2009-2010 University of York This library is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License version 3, modified in accordance with the provisions of the license to address the requirements of UK law. You should have received a copy of the modified GNU Lesser General Public License along with this library. If not, copies may be downloaded from http://www.ccp4.ac.uk/ccp4license.php This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. """ import sys from PyQt4 import QtWebKit, QtGui, QtCore import urllib2 import os class MGWebPage(QtWebKit.QWebPage): def acceptNavigationRequest(self,frame=None,request=None,type=None): for type in self.customTypes: if os.path.basename(str(request.url().path())).endswith(type): self.emit(QtCore.SIGNAL("CustomMimeTypeRequested"),request.url()) return False # Not sure it helps us much. else: return True def __init__(self,parent=None): QtWebKit.QWebPage.__init__(self,parent) self.customTypes = [] def customMimeTypes(self): return self.customTypes def setCustomMimeTypes(self,types=None): if types and type(types)==tuple or type(types)==list: self.customTypes = types def javaScriptConsoleMessage(self, message, lineNumber, sourceID): print message.toUtf8(), lineNumber, sourceID class MGWebView(QtWebKit.QWebView): def createWindow(self,type=None): view = MGWebView() view.setCustomMimeTypes(self.customMimeTypes()) self.emit(QtCore.SIGNAL("NewWindowRequested"),view) return view def LoadStarted(self,): icon = QtGui.QIcon() self.emit(QtCore.SIGNAL("IconReady"),(icon,self)) def setTarget(self,target=None): self.target=target def LoadFinished(self,ok=None): icon = self.icon() #print "Finished", self.target if self.target: myurl = self.url() myurl.setFragment(self.target) self.setTarget('') self.load(myurl) self.emit(QtCore.SIGNAL("IconReady"),(icon,self)) def customMimeTypes(self): return self.page().customMimeTypes() def setCustomMimeTypes(self,types=None): if types and type(types)==tuple or type(types)==list: self.page().setCustomMimeTypes(types) def CustomMimeTypeRequested(self,url=None): if url: self.emit(QtCore.SIGNAL("CustomMimeTypeRequested"),url) def copyHighlighted(self): QtGui.QApplication.clipboard().setText(self.selectedText()) def __init__(self,parent=None): QtWebKit.QWebView.__init__(self,parent) self.mgpage = MGWebPage(self) self.setPage(self.mgpage) self.connect(self.mgpage,QtCore.SIGNAL("CustomMimeTypeRequested"),self.CustomMimeTypeRequested) self.connect(self.mgpage,QtCore.SIGNAL("statusBarMessage(const QString&)"),self.StatusBarMessage) self.connect(self.mgpage,QtCore.SIGNAL("linkHovered(const QString &, const QString &, const QString &)"),self.LinkHovered) self.connect(self,QtCore.SIGNAL("loadFinished(bool)"),self.LoadFinished) self.connect(self,QtCore.SIGNAL("loadStarted()"),self.LoadStarted) shortcut = QtGui.QShortcut(QtGui.QKeySequence(self.tr("Ctrl+C", "Copy")),self) self.connect(shortcut,QtCore.SIGNAL("activated()"),self.copyHighlighted) """ #So we need a preferences pane for browser.... self.settings().setFontSize(QtWebKit.QWebSettings.MinimumFontSize,9) self.settings().setFontSize(QtWebKit.QWebSettings.DefaultFontSize,16) self.settings().setFontSize(QtWebKit.QWebSettings.DefaultFixedFontSize,18) self.settings().setFontFamily(QtWebKit.QWebSettings.StandardFont,"Times") """ self.setTarget('') def LinkHovered(self,link,title,content): self.emit(QtCore.SIGNAL("StatusBarMessage"),(link)) def StatusBarMessage(self,message=None): self.emit(QtCore.SIGNAL("StatusBarMessage"),(message)) class MGTabWidget(QtGui.QTabWidget): def contextMenuEvent(self,event=None): print event def __init__(self,parent=None): QtGui.QTabWidget.__init__(self,parent) class MGBrowserWindow(QtGui.QMainWindow): def StatusBarMessage(self,message=None): sb = self.statusBar() sb.showMessage(message) def setCustomMimeTypes(self,types=None): for i in range(self.tab.count()): widget = self.tab.widget(i) if hasattr(widget,"setCustomMimeTypes") and callable(widget.setCustomMimeTypes): widget.setCustomMimeTypes(types) def NewWindowRequested(self,view=None): if view: self.tab.addTab(view,view.title()) view.connect(view,QtCore.SIGNAL("CustomMimeTypeRequested"),self.CustomMimeTypeRequested) self.connect(view,QtCore.SIGNAL("NewWindowRequested"),self.NewWindowRequested) self.connect(view,QtCore.SIGNAL("StatusBarMessage"),self.StatusBarMessage) self.connect(view,QtCore.SIGNAL("titleChanged(const QString &)"),self.setTabTitles) self.connect(view,QtCore.SIGNAL("IconReady"),self.IconReady) def setTabTitles(self,title=None): for i in range(self.tab.count()): widget = self.tab.widget(i) if hasattr(widget,"title") and callable(widget.title): self.tab.setTabText(i,widget.title()) self.setWindowTitle('CCP4mg Browser: '+self.tab.tabText(self.tab.currentIndex())) widget = self.tab.widget(self.tab.currentIndex()) if hasattr(widget,"url") and callable(widget.url): if hasattr(widget.url(),"toString") and callable(widget.url().toString): self.addressEdit.setText(widget.url().toString()) self.setHistoryActionAvailability() def DeleteTab(self,ok=False): if self.tab.count()>1: self.tab.removeTab(self.tab.currentIndex()) self.setHistoryActionAvailability() def CustomMimeTypeRequested(self,url=None): self.emit(QtCore.SIGNAL("CustomMimeTypeRequested"),url) def loadMgHelp(self,file='',plugin=''): if plugin: filename = os.path.join(os.environ['CCP4MG'],'qtgui','plugins',plugin,file) self.loadFile(filename) return self.loadFile(os.path.join(os.environ['CCP4MG'],'help',file)) def loadFile(self,file): ftest = file target = None if file.find('#')>0: ftest,target = file.split('#',1) if os.path.exists(ftest): url = QtCore.QUrl.fromLocalFile(file) elif os.path.exists(ftest+'.html'): urlName = ftest+'.html' if target: urlName = urlName +'#' + target url = QtCore.QUrl.fromLocalFile(urlName) elif not file[0:4] == 'http': url = QtCore.QUrl("http://"+file) else: url = file self.loadPage(url) def loadPage(self,url): target = '' if url.scheme()=='file': if str(url.path().toAscii()).find('#')>0: urlpath,target=str(url.path().toAscii()).split('#',1) url = QtCore.QUrl.fromLocalFile(urlpath) if url.isValid: pass else: return #print "OK, trying",url.path(),target if self.tab.count()>0: widget = self.tab.currentWidget() if hasattr(widget,"load") and callable(widget.load): try: widget.setTarget(target) widget.load(url) except: exc_type, exc_value,exc_tb = sys.exc_info()[:3] print exc_type print exc_value import traceback traceback.print_tb(exc_tb) return view = MGWebView() view.connect(view,QtCore.SIGNAL("CustomMimeTypeRequested"),self.CustomMimeTypeRequested) self.connect(view,QtCore.SIGNAL("NewWindowRequested"),self.NewWindowRequested) self.connect(view,QtCore.SIGNAL("StatusBarMessage"),self.StatusBarMessage) self.connect(view,QtCore.SIGNAL("titleChanged(const QString &)"),self.setTabTitles) self.connect(view,QtCore.SIGNAL("IconReady"),self.IconReady) self.tab.addTab(view,"MGWebBrowser") def IconReady(self,args=None): icon,view = args for i in range(self.tab.count()): widget = self.tab.widget(i) if widget is view: self.tab.setTabIcon(i,icon) def __init__(self,parent=None): QtGui.QMainWindow.__init__(self,parent) self.tab = MGTabWidget(self) pb = QtGui.QPushButton() pb.setText(self.tr("Delete tab")) self.tab.setCornerWidget(pb) self.connect(pb,QtCore.SIGNAL("clicked(bool)"),self.DeleteTab) view = MGWebView() view.connect(view,QtCore.SIGNAL("CustomMimeTypeRequested"),self.CustomMimeTypeRequested) self.connect(view,QtCore.SIGNAL("NewWindowRequested"),self.NewWindowRequested) self.connect(view,QtCore.SIGNAL("StatusBarMessage"),self.StatusBarMessage) self.connect(view,QtCore.SIGNAL("titleChanged(const QString &)"),self.setTabTitles) self.connect(view,QtCore.SIGNAL("IconReady"),self.IconReady) self.tab.addTab(view,"MGWebBrowser") self.setCentralWidget(self.tab) toolbar = self.addToolBar("ToolBar") self.backAction = QtGui.QAction(self) self.forwardAction = QtGui.QAction(self) self.backAction.setText(self.tr("Back")) self.forwardAction.setText(self.tr("Forward")) toolbar.addAction(self.backAction) toolbar.addAction(self.forwardAction) self.addressEdit = QtGui.QLineEdit() self.searchEdit = QtGui.QLineEdit() searchStyle = """QLineEdit { border: 1px solid gray; border-radius: 12; border-style: inset; padding: 0 3px; } """ self.searchEdit.setStyleSheet(searchStyle) editSplitter = QtGui.QSplitter() editSplitter.addWidget(self.addressEdit) editSplitter.addWidget(self.searchEdit) self.connect(self.addressEdit,QtCore.SIGNAL("returnPressed()"),self.addressEdited) self.connect(self.searchEdit,QtCore.SIGNAL("returnPressed()"),self.searchEdited) editSplitter.setStretchFactor(0,2) toolbar.addWidget(editSplitter) self.connect(self.backAction,QtCore.SIGNAL("triggered(bool)"),self.historyBack) self.connect(self.forwardAction,QtCore.SIGNAL("triggered(bool)"),self.historyForward) self.setHistoryActionAvailability() self.connect(self.tab,QtCore.SIGNAL("currentChanged(int)"),self.setTabTitles) sb = self.statusBar() self.searchEngineString = "http://www.google.com/search?q=" reloadShortcut = QtGui.QShortcut(QtGui.QKeySequence(self.tr("Ctrl+R")),self) reloadShortcut.activated.connect(self.reloadCurrentTab) def reloadCurrentTab(self): self.tab.currentWidget().reload() def searchEdited(self): text = self.searchEdit.text().replace(QtCore.QRegExp("\\s+"),QtCore.QString("+")) self.loadPage(QtCore.QUrl(self.searchEngineString+text)) def addressEdited(self): self.loadPage(QtCore.QUrl(self.addressEdit.text())) def setHistoryActionAvailability(self): widget = self.tab.currentWidget() if hasattr(widget,"history") and callable(widget.history): history = widget.history() if history.canGoForward(): self.forwardAction.setEnabled(True) else: self.forwardAction.setEnabled(False) if history.canGoBack(): self.backAction.setEnabled(True) else: self.backAction.setEnabled(False) def historyForward(self): widget = self.tab.currentWidget() if hasattr(widget,"history") and callable(widget.history): history = widget.history() if history.canGoForward(): history.goToItem(history.forwardItem()) self.setHistoryActionAvailability() def historyBack(self): widget = self.tab.currentWidget() if hasattr(widget,"history") and callable(widget.history): history = widget.history() if history.canGoBack(): history.goToItem(history.backItem()) self.setHistoryActionAvailability() def minimumSizeHint(self): return QtCore.QSize(QtGui.QApplication.desktop().width()/3, QtGui.QApplication.desktop().height()/2) if __name__ == '__main__': if "-quit" in sys.argv: sys.exit() def DoSomething(url=None): print "Do something with", url app = QtGui.QApplication(sys.argv) try: if sys.platform == 'win32': homedir = os.environ.get('USERPROFILE') else: homedir = os.environ.get('HOME') except: pass if homedir and os.path.exists(homedir): webkit_db = os.path.join(homedir,'.qwebkit_idb') if os.path.exists(webkit_db): QtWebKit.QWebSettings.setIconDatabasePath(webkit_db) else: try: os.mkdir(webkit_db) QtWebKit.QWebSettings.setIconDatabasePath(webkit_db) except: # Favicons disabled pass browser = MGBrowserWindow() browser.connect(browser,QtCore.SIGNAL("CustomMimeTypeRequested"),DoSomething) browser.setCustomMimeTypes(["pdb","mtz"]) browser.show() browser.raise_() #browser.loadPage(QtCore.QUrl("file:///Users/stuart/Qt4.4/test.html")) #browser.loadPage(QtCore.QUrl("file:///y/people/mcnicholas/Qt4.4/test.html")) #browser.loadPage(QtCore.QUrl("file:///richelieu/stuart/ccp4-jhbuild-distutils/WebGL/js-pimple.html")) if len(sys.argv)>1: browser.loadPage(QtCore.QUrl(sys.argv[1])) sys.exit(app.exec_())