"""
CCP4WebBrowser.py: CCP4 GUI Project
Copyright (C) 2001-2008 University of York, CCLRC
Copyright (C) 2009-2010 University of York
Copyright (C) 2011-2014 Science & Technology Facilities Council
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.
"""
"""
Liz Potterton Jan 2010 - Copied from MGWebBrowser with changes to make stand-alone and to enable
Qt plugins and custom mime types
Feb 2010 - Make menus/toolbars customisable, add CCP4ProjectManger as placeholder
"""
##@package CCP4WebBrowser (QtWebKit) The web browser framework
import os
import sys
import time
import glob
from PyQt4 import QtWebKit, QtGui, QtCore
from qtgui import CCP4WebView
from core import CCP4Modules
from core.CCP4ErrorHandling import *
def setupWebkit():
try: # nice.... not.... also our old friend the try-except-pass (check this is indent'ed ok )
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
def checkRunningJobs():
runningJobs = CCP4Modules.PROJECTSMANAGER().db().getRunningJobs()
topRunningJobs = {}
for job in runningJobs:
if job[5] is None and len(job[1].split('.')) == 1:
projectName=CCP4Modules.PROJECTSMANAGER().db().getProjectInfo(projectId=job[3],mode='projectname')
if projectName in topRunningJobs:
topRunningJobs[projectName].append(job)
else:
topRunningJobs[projectName] = [job]
return topRunningJobs
def exitBrowser():
if "-dbLocal" in sys.argv:
topRunningJobs = checkRunningJobs()
if len(topRunningJobs) > 0:
message = "The following jobs are still running and you are in 'Local database mode'."
if bool(CCP4Modules.PREFERENCES().DBLOCAL_QUIT_RUNNING):
message += "
If you quit, results from these running jobs may be lost but the job will appear to still be running when you restart CCP4i2.
Do you really want to quit?
"
else:
message += "
Please wait for these jobs to finish before quitting. Or kill them if you really want to quit now.
"
for proj,jobs in topRunningJobs.items():
message += "Project: "+proj+"
"
for job in jobs:
message += str(job[1]) + " " + job[2] + "
"
message += "
"
mb = QtGui.QMessageBox(QtGui.QMessageBox.Question,"Jobs still running",message)
if bool(CCP4Modules.PREFERENCES().DBLOCAL_QUIT_RUNNING):
mb.addButton("Really quit",QtGui.QMessageBox.AcceptRole)
mb.addButton("Cancel",QtGui.QMessageBox.RejectRole)
rv = mb.exec_()
if rv == 1:
return
else:
mb.addButton("Cancel",QtGui.QMessageBox.RejectRole)
rv = mb.exec_()
return
purgeStatusFiles(0)
from qtgui import CCP4ProjectViewer
#print '*CCP4WebBrowser exitBrowser'
CMainWindow.queryClose=False
rv = saveStatus()
purgeStatusFiles(2)
for win in CCP4ProjectViewer.CProjectViewer.Instances:
win.Exit()
CCP4Modules.PREFERENCES().save()
#print 'purgeStatusFiles done'
CCP4Modules.QTAPPLICATION().setActiveWindow(CCP4Modules.WEBBROWSER())
CCP4Modules.QTAPPLICATION().closeAllWindows()
def saveStatus():
from core import CCP4Utils
from qtgui import CCP4I1Projects
from core import CCP4File
if CMainWindow.STATUS_SAVED:
return ''
from lxml import etree
from qtgui import CCP4ProjectViewer
body = etree.Element('body')
root = etree.Element('windows')
body.append(root)
#print 'saveStatus',CBrowserWindow.Instances,CCP4ProjectViewer.CProjectViewer.Instances
#import traceback
#traceback.print_stack(limit=5)
for win in CCP4I1Projects.CI1ProjectViewer.Instances:
win.Exit()
for win in CBrowserWindow.Instances:
winEle = etree.Element('browser')
try:
size = (win.size().width(),win.size().height())
sizeEle = etree.Element('windowSize')
sizeEle.text = str(size[0]) + ',' + str(size[1])
winEle.append(sizeEle)
except:
pass
#print 'CMainWindow.saveStatus browser',win.tab().count()
for ii in range(win.tab().count()):
tabEle = etree.Element('tab')
winEle.append(tabEle)
fileEle = etree.Element('filename')
try:
url = win.tab().widget(ii).url()
except:
pass
else:
#filename = os.path.normpath(str(win.tab().widget(ii).fileName))
#print 'CMainWindow.saveStatus',url.isLocalFile()
if url.isLocalFile():
filename = url.toLocalFile().__str__().strip('file:')
if not os.path.exists(filename) and os.path.splitext(filename)[1] == '.htm':
filename = filename + 'l'
if os.path.relpath(filename, CCP4Utils.getCCP4I2Dir()).startswith('docs'):
fileEle.text = '$CCP4I2/' + os.path.relpath(filename, CCP4Utils.getCCP4I2Dir())
else:
fileEle.text = filename
else:
fileEle.text = url.toString().__str__()
#print 'CMainWindow.saveStatus browser tab file',win.tab().widget(ii).fileName
tabEle.append(fileEle)
title = win.tab().widget(ii).title()
if title is not None:
titleEle = etree.Element('title')
titleEle.text = title
tabEle.append(titleEle)
root.append(winEle)
for win in CCP4ProjectViewer.CProjectViewer.Instances:
size = None
try:
projectName = CCP4Modules.PROJECTSMANAGER().db().getProjectInfo(projectId=win.getProject(), mode='projectname')
jobNumber = win.getOpenJobNumber()
size = (win.size().width(),win.size().height())
except:
pass
else:
winEle = etree.Element('projectViewer')
projectEle = etree.Element('project')
#print 'CMainWindow.saveStatus projectName',projectName
projectEle.text = projectName
winEle.append(projectEle)
if jobNumber is not None:
jobEle = etree.Element('openJobNumber')
jobEle.text = str(jobNumber)
winEle.append(jobEle)
if size is not None:
sizeEle = etree.Element('windowSize')
sizeEle.text = str(size[0])+','+str(size[1])
winEle.append(sizeEle)
# Issues with handing ByteArray - skip this for now
#ele = etree.SubElement(projectEle,'headerState')
#ele.text = win.projectWidget().getHeaderState()
root.append(winEle)
#print 'CCP4WebBrowser.saveStatus',etree.tostring(body,pretty_print=True)
statusFile = os.path.join(CCP4Utils.getDotDirectory(), 'status', 'status_' + str(int(time.time())) + '.ccp4i2_status.xml')
f= CCP4File.CI2XmlDataFile(statusFile)
f.header.function='STATUS'
f.header.setCurrent()
f.saveFile(bodyEtree=body)
CMainWindow.STATUS_SAVED = True
print 'CCP4i2 status saved to', statusFile
return statusFile
def restoreStatus():
from core import CCP4Utils
from qtgui import CCP4ProjectViewer
from qtcore import CCP4CustomMimeTypes
from lxml import etree
# For now just try to restore projects
statusEtree = retrieveStatus()
if statusEtree is None:
return
nBrowserWindows = 0
for winEle in statusEtree.iterchildren():
#print 'CCP4WebBrowser.restoreStatus', winEle.tag
if str(winEle.tag) == 'projectViewer':
for projectEle in winEle.iter('project'):
projectName=projectEle.text
try:
projectId = CCP4Modules.PROJECTSMANAGER().db().getProjectId(projectName=projectName)
except:
projectId = None
print 'Unable to open project - ' + projectEle.text + '- not found in database'
# 'restoreStatus ',projectEle.text,projectId
if projectId is not None:
# Do we know the open job?
#print 'Opening project:',projectEle.text
jobId= None
jobEle = winEle.find('openJobNumber')
if jobEle is not None:
try:
jobId = CCP4Modules.PROJECTSMANAGER().db().getJobId(jobNumber=str(jobEle.text), projectName=projectName)
except CException as e:
#print e.report()
jobId = None
try:
print 'Opening Job:', jobEle.text, jobId
proj = CCP4ProjectViewer.CProjectViewer(projectId=projectId, jobId=jobId)
try:
sizeStr = winEle.find('windowSize').text.split(',')
size = (int(sizeStr[0]), int(sizeStr[1]))
except:
size = CCP4ProjectViewer.DEFAULT_WINDOW_SIZE
proj.resize(size[0], size[1])
# Issues with handing ByteArray - skip this for now
#headerEle = winEle.find('headerState')
#if headerEle is not None:
# proj.projectWidget().setHeaderState(str(headerEle.text()))
proj.menuBar().show()
proj.show()
proj.raise_()
except:
print "Failed to open project", projectId, jobId
elif str(winEle.tag) == 'browser':
if nBrowserWindows == 0:
browser = CCP4Modules.WEBBROWSER()
else:
browser = CBrowserWindow()
browser.show()
browser.raise_()
nBrowserWindows = nBrowserWindows + 1
for tab in winEle.iterchildren():
if tab.tag == 'windowSize':
try:
sizeStr = tab.text.split(',')
browser.resize(int(sizeStr[0]), int(sizeStr[1]))
except:
pass
elif tab.tag == 'tab':
fileName = None
title = None
for ele in tab.iterchildren():
if ele.tag == 'filename':
fileName = str(ele.text)
#print 'restoreStatus fileName',fileName
if fileName.startswith('$CCP4I2'):
fileName = os.path.join(CCP4Utils.getCCP4I2Dir(), fileName[8:])
elif ele.tag == 'title':
title = str(ele.text)
if fileName is not None:
#print 'Opening file:',fileName
if fileName.startswith('http'):
url = QtCore.QUrl(fileName)
browser.loadPage(url)
else:
browser.openFile(fileName, title=title, internal=True)
def applyCommandLine(args):
# If there is a file/project on the com line.
from core import CCP4Utils
from qtgui import CCP4ProjectViewer
#print 'CCP4Browser.applyCommandLine',args
iArg = 0
while iArg < len(args):
filepath = None
if args[iArg][0:2] == '-t':
top_path = CCP4Utils.getCCP4I2Dir()
filepath = os.path.join(top_path, 'test', 'data', 'test_plugin.html')
else:
projectName = args[iArg]
try:
projectId = CCP4Modules.PROJECTSMANAGER().db().getProjectId(projectName=projectName)
except:
projectId = None
#print 'CCP4WebBrowser.applyCommandLine projectId', projectId
if projectId is None:
filepath = os.path.abspath(args[iArg])
#print 'CCP4Browser.applyCommandLine filepath', filepath
if os.path.exists(filepath):
#print 'Opening file:', filepath
CCP4Modules.WEBBROWSER().openFile(filepath, internal=True)
else:
print args[iArg],'not recognised as project name or file'
else:
#print 'Opening project:',projectName
proj = CCP4ProjectViewer.CProjectViewer(projectId=projectId)
proj.resize(CCP4ProjectViewer.DEFAULT_WINDOW_SIZE[0], CCP4ProjectViewer.DEFAULT_WINDOW_SIZE[1])
proj.show()
proj.raise_()
iArg = iArg + 1
if len(CBrowserWindow.Instances) + len(CCP4ProjectViewer.CProjectViewer.Instances) <= 0:
#print 'Opening default browser window'
browser = CBrowserWindow()
browser.show()
def retrieveStatus():
from core import CCP4File
from core import CCP4Utils
statusFileList = glob.glob(os.path.join(CCP4Utils.getDotDirectory(), 'status', 'status_*.ccp4i2_status.xml'))
if len(statusFileList) == 0:
return None
else:
statusFileList.sort()
print 'Retrieving status file:' + statusFileList[-1]
f = CCP4File.CI2XmlDataFile(statusFileList[-1])
body = f.getBodyEtree()
root = body.find('windows')
return root
def purgeStatusFiles(leave=1):
from core import CCP4Utils
#print 'purgeStatusFiles leave',leave
statusFileList = glob.glob(os.path.join(CCP4Utils.getDotDirectory(), 'status', 'status_*.ccp4i2_status.xml'))
#print 'purgeStatusFiles',statusFileList
if leave == 0:
for sFile in statusFileList:
os.remove(sFile)
elif len(statusFileList) > leave:
for sFile in statusFileList[0:-leave]:
os.remove(sFile)
#-------------------------------------------------------------------
def OPENFILE(fileName=None, cformat=None, title=None, toFront=False):
#-------------------------------------------------------------------
mimeTypeHandler = CCP4Modules.MIMETYPESHANDLER()
if os.path.isdir(fileName):
cformat = 'dir'
if mimeTypeHandler is None:
# No handler so just throw it at web browser and hope
if cformat is None:
cformat = 'text/html'
else:
if cformat is None:
cformat = mimeTypeHandler.formatFromFileExt(fileName)
if not mimeTypeHandler.isSupportedFormat(format):
cformat = 'text/html'
#print 'CCP4WebBrowser.OPENFILE format',fileName,format
if mimeTypeHandler.useDesktopServices(format):
abs_fileName = os.path.abspath(fileName)
#print 'calling QDesktopServices',abs_fileName
url = QtCore.QUrl.fromLocalFile(abs_fileName)
rv = QtGui.QDesktopServices.openUrl(url)
if not rv:
QtGui.QMessageBox.warning(None, 'CCP4i2 display ' + fileName,
'Attempting to display file ' + os.path.split(abs_fileName)[-1] + '\nusing desktop services failed')
return None
widgetClassList = mimeTypeHandler.getViewers(format)
if len(widgetClassList) > 0:
widgetClass = widgetClassList[0]
if isinstance(widgetClass,str):
# This is a keyword for the launcher
CCP4Modules.LAUNCHER().openInViewer(viewer=widgetClass, fileName=fileName)
return None
CCP4Modules.WEBBROWSER().openFile(fileName=fileName, format=format, title=title, toFront=toFront)
class CTabWidget(QtGui.QTabWidget):
def __init__(self, parent=None, name=None, mini=False):
QtGui.QTabWidget.__init__(self, parent)
self.setObjectName(name)
self.connect(self, QtCore.SIGNAL('currentChanged(int)'), self.handleCurrentChanged)
self.currentOpen = -1
#try:
# self.setTabsCloseable(True)
#except:
if mini:
self.setCornerWidget(QtGui.QPushButton(self.tr("Expand window")))
else:
self.setCornerWidget(QtGui.QPushButton(self.tr("Close tab")))
def deleteTabWidget(self, idx=None, widget=None):
if idx is None:
for ii in range(self.count()):
if self.widget(ii) == widget:
idx = ii
break
if idx is None: return
self.widget(idx).handleTabbedClosed()
self.widget(idx).close()
self.widget(idx).deleteLater()
# We are keeping track of currentOpen to be sure to
# call handleTabbedClosed() when necessary
if self.currentOpen > idx:
self.currentOpen = self.currentOpen - 1
elif self.currentOpen == idx:
self.currentOpen = -1
self.removeTab(idx)
def handleCurrentChanged(self,indx):
#print 'CTabWidget.handleCurrentChanged', indx
if self.currentOpen >= 0:
self.widget(self.currentOpen).handleTabbedClosed()
#print 'CTabWidget.handleCurrentChanged',self.currentOpen,self.widget(self.currentOpen)
self.currentOpen = indx
self.parent().parent().editSplitter.addressEdit.setText(self.widget(indx).title())
self.widget(indx).handleTabbedOpen()
self.parent().parent().updateActionEnabled()
def closeTabWidget(self,obj):
for ii in range(len(self.widget)):
if self.widget[ii] == obj:
self.deleteTabWidget(ii)
class CEditSplitter(QtGui.QSplitter):
def __init__(self,parent):
QtGui.QSplitter.__init__(self,parent)
self.addressEdit = QtGui.QLineEdit()
self.searchEdit = QtGui.QLineEdit()
searchStyle = """QLineEdit {border: 1px solid gray;border-radius: 6;border-style: inset;padding: 0 3px;}"""
self.searchEdit.setStyleSheet(searchStyle)
self.addWidget(self.addressEdit)
self.addWidget(self.searchEdit)
self.setStretchFactor(0, 2)
class CMenuBar(QtGui.QMenuBar):
def __init__(self, parent):
from core.CCP4Bazaar import bzrlib_exists
QtGui.QMenuBar. __init__(self, parent)
self.menuDefinitions = {}
for menuName, menuTitle in [['File', '&File'], ['Edit', '&Edit'],
['Utilities', '&Utilities'], ['Projects', '&Projects'],['Help', 'Help']]:
self.addMenu(menuName, menuTitle)
self.menuDefinitions['File'] = ['open_browser', 'open', 'sep','close_window', 'quit']
#self.menuDefinitions['Edit'] = ['find','preferences','ccp4i2_config']
#It is a bit cheeky inserting help_about here, but we know that OS X will intercept this and stick in Application Menu.
#And the 'Edit' menu does not seem to be redrawn (at present!). I guess a special '_dummy' menu as MG does it would allow
#'Edit' to be dynamic in future.
if sys.platform == "darwin":
self.menuDefinitions['Edit'] = ['find', 'preferences','help_about']
else:
self.menuDefinitions['Edit'] = ['find', 'preferences']
self.menuDefinitions['History'] = []
self.menuDefinitions['Utilities'] = ['listProcesses', 'manageImportFiles',
['Program log', 'programPrintLog','programHTTPLog'],'clearStatusFiles',
'editScript', 'sendReport',['System administrator tools','update_core',
'serverSetup','import_task'],
['Developer tools','redo_report','view_report_source','remake_cached_lookups','view_test_report',
'export_task','list_tasks','grab_task','compress_demo_data','auto_task_docs']]
self.menuDefinitions['Customisation'] = ['manageWorkflows', 'patchComFile', 'customTask', 'importJob']
self.menuDefinitions['Projects'] = ['manager_projects',
'new_project',['View old CCP4i projects', 'open_i1projects_default',
'open_i1projects_select']]
if sys.platform == "darwin":
self.menuDefinitions['Help'] = ['help_quickstart', 'help_quickexpert', 'help_youtube',
'task_docs', 'welcome_ccp4i2', 'help_ccp4i2', 'help_ccp4_home',
'help_updates', 'help_license']
else:
self.menuDefinitions['Help'] = ['help_about', 'help_quickstart', 'help_quickexpert', 'help_youtube',
'task_docs', 'welcome_ccp4i2', 'help_ccp4i2', 'help_ccp4_home',
'help_updates', 'help_license']
if bzrlib_exists:
self.menuDefinitions['Utilities'][6].insert(1, 'update_gui')
# Beware need to define the 'quit' in File menu at startup for the slot to exitBrowser() to work
# This is likely a mac-specific thing since the quit gets move to application menu
from qtgui import CCP4GuiUtils
CCP4GuiUtils.populateMenu(self.parent(), self.menuWidget('Edit'), self.menuDefinition('Edit'), default_icon='')
CCP4GuiUtils.populateMenu(self.parent(), self.menuWidget('File'), self.menuDefinition('File'), default_icon='')
def menuWidget(self,menuName):
return self.findChild(QtGui.QMenu, menuName)
def updateMenu(self, menuName):
from qtgui import CCP4GuiUtils
import functools
menuWidget = self.menuWidget(menuName)
if menuWidget is None:
pass
elif menuName == 'Projects':
recentProjects = CCP4Modules.PROJECTSMANAGER().db().getRecentProjects(order='access', limit=11)
menuDefn = ['manage_projects', 'new_project', 'export_project',
'import_project', ['View old CCP4i projects', 'open_i1projects_default',
'open_i1projects_select'], 'sep']
for projectId, projectName, accessTime in recentProjects[:10]:
if not self.parent().actionDefinitions.has_key('open_project_' + str(projectId)):
self.parent().setActionDefinition('open_project_' + str(projectId),
dict(text = projectName, tip = "Open this project",
slot = functools.partial(self.parent().openProject, projectId, projectName),
enabled = 1, checkable = 1,
checked = functools.partial( self.isProjectOpen, projectId)))
menuDefn.append('open_project_' + str(projectId))
menuDefn.append('more_projects')
# Enable more_projects if >10 projects in db
self.parent().actionDefinitions['more_projects']['enabled'] = len(recentProjects) > 10
menuWidget.clear()
CCP4GuiUtils.populateMenu(self.parent(), menuWidget, menuDefn, default_icon='')
#self._redrawProjectMenu = False
elif menuName == 'Edit':
pass
elif menuName == 'Utilities':
menuWidget.clear()
menuDefn = [['Copy demo data to project']]
if self.parent().isProjectViewer():
testDatasets = CCP4Modules.DEMODATAMANAGER().getTestDatasets()
for dataset,label in testDatasets:
self.parent().setActionDefinition('download_test_' + dataset,
dict(text=label, tip="Copy this data to project directory",
slot = functools.partial(CCP4Modules.DEMODATAMANAGER().copyDemoDataToProject,
self, self.parent().taskFrame.openJob.projectId, dataset),
enabled = self.parent().isProjectViewer))
menuDefn[0].append('download_test_' + dataset)
menuDefn[0].append('sep')
menuDefn[0].append('demo_data_info')
menuDefn[0].append('download_demo_data')
menuDefn.extend( self.menuDefinitions['Utilities'] )
CCP4GuiUtils.populateMenu(self.parent(), menuWidget, menuDefn, default_icon='')
else:
menuWidget.clear()
CCP4GuiUtils.populateMenu(self.parent(), menuWidget, self.menuDefinition(menuName), default_icon='')
def isProjectOpen(self, projectId):
from qtgui import CCP4ProjectViewer
for proj in CCP4ProjectViewer.CProjectViewer.Instances:
if hasattr(proj,'openJob') and proj.openJob.projectId == projectId:
return True
return False
def addMenu(self, menuName=None, menuTitle=None, updateFunction=None):
import functools
if menuName is None or menuTitle is None:
print 'ERROR in CMenuBar.addMenu; no menu name or no menu title given'
return None
widget = self.menuWidget(menuName)
if widget is None:
widget = QtGui.QMenuBar.addMenu(self, menuTitle)
widget.setObjectName(menuName)
if updateFunction is None:
self.connect(widget, QtCore.SIGNAL("aboutToShow()"), functools.partial(self.updateMenu, menuName))
else:
self.connect(widget, QtCore.SIGNAL("aboutToShow()"), functools.partial(updateFunction, menuName))
return widget
def removeMenu(self, menuName=''):
# Save current menus, clear and add all menus again
currentMenuList = []
found = False
currentMenuWidgets = self.findChildren(QtGui.QMenu)
for w in currentMenuWidgets:
name = str(w.objectName())
if name == menuName:
found = True
else:
currentMenuList.append([str(w.objectName()), str(w.title())])
if found:
self.clear()
for menuName, menuTitle in currentMenuList:
self.addMenu(menuName, menuTitle)
def setMenuTitle(self, menuName='', menuTitle=''):
widget = self.menuWidget(menuName)
if widget is not None:
widget.setTitle(menuTitle)
def menuDefinition(self, menuName=''):
return self.menuDefinitions.get(menuName,[])
def setMenuDefinition(self, menuName='', definition=[]):
self.menuDefinitions[menuName] = definition
def appendToMenu(self, menuName='', menuItem=''):
# menuItem should be the name of an action or 'sep' (separator)
if not self.menuDefinitions.has_key(menuName):
print 'ERROR in CMenuBar.appendToMenu: ' + menuName + ' menu does not exist'
self.menuDefinitions[menuName].append(menuItem)
class CToolBar(QtGui.QToolBar):
#FIXME "toPyObject()" should probably be "value()" in PyQt5.
#FIXME And all the use of str should go in PyQt5.
toolBarPreferencesMapping = {
"task_menu" : "SHOW_TASK_MENU_TOOLBUTTON",
"job_search" : "SHOW_JOB_SEARCH_TOOLBUTTON",
"export_project" : "SHOW_EXPORT_PROJECT_TOOLBUTTON",
"run" : "SHOW_RUN_TOOLBUTTON",
"run_remote" : "SHOW_RUN_REMOTE_TOOLBUTTON",
"clone" : "SHOW_CLONE_TOOLBUTTON",
"task_help" : "SHOW_TASK_HELP_TOOLBUTTON",
"references" : "SHOW_REFERENCES_TOOLBUTTON",
"export_mtz" : "SHOW_EXPORT_MTZ_TOOLBUTTON",
"view_coot" : "SHOW_VIEW_COOT_TOOLBUTTON",
"view_ccp4mg" : "SHOW_VIEW_CCP4MG_TOOLBUTTON"
}
def __init__(self,parent,name='',title=''):
QtGui.QToolBar.__init__(self, title, parent)
self.setObjectName(name)
if hasattr(CCP4Modules.PREFERENCES(), "TOOLBARBUTTONSSTYLE"):
self.setToolButtonStyle(int(CCP4Modules.PREFERENCES().TOOLBARBUTTONSSTYLE))
self.setIconSize(QtCore.QSize(24, 24))
self.definition = []
def append(self,toolName=''):
if not self.definition.count(toolName):
self.definition.append(toolName)
self.redraw()
def extend(self,toolNameList=[]):
for toolName in toolNameList:
if not self.definition.count(toolName):
self.definition.append(toolName)
self.redraw()
def remove(self,toolName=''):
if self.definition.count(toolName):
self.definition.remove(toolName)
self.redraw()
def redraw(self):
self.clear()
from qtgui import CCP4GuiUtils
CCP4GuiUtils.populateToolBar(parent=self.parent(), toolBarWidget=self, definition=self.definition)
children = self.findChildren(QtGui.QToolButton)
for child in children:
if child.defaultAction() is not None:
theName = str(child.defaultAction().objectName())
if theName in self.toolBarPreferencesMapping:
if CCP4Modules.PREFERENCES().get(self.toolBarPreferencesMapping[theName]) == False:
child.defaultAction().setVisible(False)
def editPreferences(self):
import CCP4ProjectViewer
prefWidget = QtGui.QDialog()
prefWidget.setWindowTitle("Edit visible tool buttons")
children = self.findChildren(QtGui.QToolButton)
listWidget = QtGui.QListWidget()
layout = QtGui.QVBoxLayout()
prefWidget.setLayout(layout)
layout.addWidget(listWidget)
for child in children:
if child.defaultAction() is not None:
item = QtGui.QListWidgetItem()
item.setText(child.defaultAction().text())
item.setIcon(child.defaultAction().icon())
listWidget.addItem(item)
item.setFlags(item.flags() | QtCore.Qt.ItemIsUserCheckable)
item.setCheckState(QtCore.Qt.Unchecked)
if child.defaultAction().isVisible():
item.setCheckState(QtCore.Qt.Checked)
item.setData(QtCore.Qt.UserRole,child)
def setItemVisibilities(item):
checkState, tb = item.checkState(), item.data(QtCore.Qt.UserRole).toPyObject()
theName = tb.defaultAction().objectName()
for window in CCP4ProjectViewer.CProjectViewer.Instances:
acts = window.findChildren(QtGui.QAction,theName)
for act in acts: #Should be length 0 or 1
if checkState:
act.setVisible(True)
else:
act.setVisible(False)
mapping = self.toolBarPreferencesMapping[str(theName)]
if checkState:
val = True
else:
val = False
#FIXME - Aargh. There must be a nicer way.
if mapping == "SHOW_TASK_MENU_TOOLBUTTON":
CCP4Modules.PREFERENCES().SHOW_TASK_MENU_TOOLBUTTON.set(val)
elif mapping == "SHOW_JOB_SEARCH_TOOLBUTTON":
CCP4Modules.PREFERENCES().SHOW_JOB_SEARCH_TOOLBUTTON.set(val)
elif mapping == "SHOW_EXPORT_PROJECT_TOOLBUTTON":
CCP4Modules.PREFERENCES().SHOW_EXPORT_PROJECT_TOOLBUTTON.set(val)
elif mapping == "SHOW_RUN_TOOLBUTTON":
CCP4Modules.PREFERENCES().SHOW_RUN_TOOLBUTTON.set(val)
elif mapping == "SHOW_RUN_REMOTE_TOOLBUTTON":
CCP4Modules.PREFERENCES().SHOW_RUN_REMOTE_TOOLBUTTON.set(val)
elif mapping == "SHOW_CLONE_TOOLBUTTON":
CCP4Modules.PREFERENCES().SHOW_CLONE_TOOLBUTTON.set(val)
elif mapping == "SHOW_TASK_HELP_TOOLBUTTON":
CCP4Modules.PREFERENCES().SHOW_TASK_HELP_TOOLBUTTON.set(val)
elif mapping == "SHOW_REFERENCES_TOOLBUTTON":
CCP4Modules.PREFERENCES().SHOW_REFERENCES_TOOLBUTTON.set(val)
elif mapping == "SHOW_EXPORT_MTZ_TOOLBUTTON":
CCP4Modules.PREFERENCES().SHOW_EXPORT_MTZ_TOOLBUTTON.set(val)
elif mapping == "SHOW_VIEW_COOT_TOOLBUTTON":
CCP4Modules.PREFERENCES().SHOW_VIEW_COOT_TOOLBUTTON.set(val)
elif mapping == "SHOW_VIEW_CCP4MG_TOOLBUTTON":
CCP4Modules.PREFERENCES().SHOW_VIEW_CCP4MG_TOOLBUTTON.set(val)
listWidget.itemChanged.connect(setItemVisibilities)
prefWidget.exec_()
def contextMenuEvent(self,e):
if self.parent().objectName() != 'projectViewer':
return
menu = QtGui.QMenu(self)
custAct = QtGui.QAction("Customize",self)
custAct.triggered.connect(self.editPreferences)
menu.addAction(custAct);
menu.exec_(e.globalPos());
def isAlive(qobj):
import sip
try:
sip.unwrapinstance(qobj)
except RuntimeError:
return False
return True
def mainWindowIcon():
if CMainWindow._MAINWINDOWICON is None:
from core import CCP4Utils
fileName = os.path.join(CCP4Utils.getCCP4I2Dir(), 'qticons', 'ccp4.png')
CMainWindow._MAINWINDOWICON = QtGui.QIcon(QtGui.QPixmap(fileName))
return CMainWindow._MAINWINDOWICON
class CMainWindow(QtGui.QMainWindow):
projectManagerDialog = None
queryClose = False
STATUS_SAVED = False
_MAINWINDOWICON = None
ERROR_CODES = {201 : {'description' : 'Error opening zip file for write'},
202 : {'description' : 'Error saving directory to zip file'},
203 : {'description' : 'Error closing zip file from read'},
204 : {'description' : 'Error opening zip file to read'},
205 : {'description' : 'Error extracting zip file from directory'},
206 : {'description' : 'Compressed task file does not contain appropriately named task'},
207 : {'description' : 'Can not import task as it requires overwriting exisiting task'},
208 : {'description' : 'Error deleting existing task directory'}, # KJS : Changed below to 209 .....
209 : {'description' : 'Selected inappropriate directory to save as compressed task file'}}
def backupDB(self):
CCP4Modules.PROJECTSMANAGER().backupDB()
def backupDBXML(self):
CCP4Modules.PROJECTSMANAGER().backupDBXML()
def __init__(self, parent=None):
from qtcore import CCP4UpdateManager
QtGui.QMainWindow.__init__(self,parent)
self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
self.setWindowIcon(mainWindowIcon())
# Remove access to bzr as Andrey claims it causes access to repository that is acting badly possibly due to loading
try:
from core import CCP4Update
self.version = CCP4Update.get_ccp4_str() + ' '
except:
self.version = 'DEVELOPMENT CCP4i2'
self.preferenceWindow=None
self.configWindow=None
self.fileDialog = None
self.findFrame= None
self.um = CCP4UpdateManager.um
self.initialiseActionDefinitions()
self.setMenuBar(CMenuBar(self))
def closeEvent(self, event):
from qtgui import CCP4ProjectViewer
from qtgui import CCP4I1Projects
if CBrowserWindow.Dummy is None:
nOpen = 0
else:
nOpen = len(CBrowserWindow.Dummy.findChildren(QtGui.QDialog))
#print 'closeEvent Dummy.findChildren',nOpen
nOpen = nOpen + len(CBrowserWindow.Instances) + len(CCP4ProjectViewer.CProjectViewer.Instances) + len(CCP4I1Projects.CI1ProjectViewer.Instances)
#print 'closeEvent Instances',nOpen
#print 'closingDown',CCP4Modules.QTAPPLICATION().closingDown()
if nOpen > 1:
self.close()
event.accept()
else:
if CMainWindow.queryClose:
rv = QtGui.QMessageBox.question(self,'Close CCP4Browser','Close CCP4 Browser?',
QtGui.QMessageBox.Close|QtGui.QMessageBox.Cancel, QtGui.QMessageBox.Cancel)
else:
rv = QtGui.QMessageBox.Close
if rv == QtGui.QMessageBox.Close:
self.Exit()
saveStatus()
purgeStatusFiles(2)
event.accept()
else:
event.ignore()
def Exit(self):
pass
def windowTitle(self):
return str(QtGui.QMainWindow.windowTitle(self))
def initialiseActionDefinitions(self):
import functools
self.actionDefinitions = {}
self.actionDefinitions['quit'] = dict(text='Quit CCP4i2', tip='Close all CCP4i2 windows', slot=exitBrowser)
self.actionDefinitions['help_about'] = dict(text="About", tip="CCP4i2 background",
slot=self.showAbout)
self.actionDefinitions['welcome_ccp4i2'] = dict(text="Welcome - options to get started",
tip="Options to set up CCP4i2 Project",
slot=functools.partial(self.showHelp, 'ccp4i2'),
shortcut=self.tr('cmd+P'), icon='ccp4')
self.actionDefinitions['help_quickstart'] = dict(text="Quickstart - 10 minute intro",
tip="Quick introduction to using i2",
slot = functools.partial(self.showHelp, 'quickstart'),
shortcut = self.tr('cmd+Q'), icon='ccp4')
self.actionDefinitions['help_quickexpert'] = dict(text = "Quick expert - more quick hints",
tip = "Part 2 of quick introduction to i2",
slot = functools.partial(self.showHelp, 'quickexpert'), icon='ccp4')
self.actionDefinitions['help_youtube'] = dict(text = "View YouTube video",
tip = "Quick introduction iin youtube (6mins)",
slot = functools.partial(self.showHelp, 'youtube'), icon = 'ccp4')
self.actionDefinitions['help_ccp4i2'] = dict(text = "CCP4i2 Help", tip = "Documentation and 'where to start'",
slot = functools.partial(self.showHelp, 'tutorial'),
shortcut = self.tr('cmd+H'), icon='ccp4')
self.actionDefinitions['task_docs'] = dict(text = "Task documentation", tip = "Documentation for the individual tasks",
slot = functools.partial(self.showHelp, 'task_docs'), icon = 'ccp4')
self.actionDefinitions['help_ccp4_home'] = dict(text = "CCP4 Home Page", tip = "For further information on CCP4",
slot = functools.partial(self.showHelp, 'ccp4_home'), icon = 'ccp4')
self.actionDefinitions['help_updates'] = dict(text = "CCP4 Updates", tip = "",
slot = functools.partial(self.showHelp, 'updates'))
self.actionDefinitions['help_license'] = dict(text = "CCP4 Licence", tip = "",
slot = functools.partial(self.showHelp, 'license'),)
self.actionDefinitions['open'] = dict(text = "Open file", tip = "Open html, text, image or log file",
slot = self.openFileDialog, icon = 'fileopen', shortcut = QtGui.QKeySequence.Open, enabled = self.isNotProjectViewer)
self.actionDefinitions['close_window'] = dict(text = "Close window", tip = "Close this CCP4i2 window",
slot = self.close, shortcut = QtGui.QKeySequence.Close)
self.actionDefinitions['save'] = dict(text = "Save", tip = "Save to file", slot = self.handleSave,
enabled = self.widgetIsSaveable)
self.actionDefinitions['print'] = dict(text = "Print", tip = "Print file", slot = self.handlePrint,
enabled = self.widgetIsPrintable)
#FIXME - What does this do?
self.actionDefinitions['run'] = dict(text = "Run", tip = "Run script", slot = self.handleRun,
enabled = self.widgetIsRunable)
self.actionDefinitions['find'] = dict(text = "Find", tip = "Find in file", slot = self.openFind, icon = 'search',
checkable = 1, checked = self.isFindFrameOpen, enabled = self.widgetIsSearchable, shortcut = QtGui.QKeySequence.Find)
self.actionDefinitions['preferences'] = dict(text = "Preferences", slot = self.openPreferences,
checkable = 1, checked = self.isPreferencesOpen,)
self.actionDefinitions['ccp4i2_config'] = dict(text = "Configure CCP4i2", slot = self.openConfig,
checkable = 1, checked = self.isConfigOpen,)
self.actionDefinitions['close_tab'] = dict(text = "Close tab", tip = "Close the currently displayed file",
slot = self.deleteTab, enabled = 1)
self.actionDefinitions['open_browser'] = dict(text = "Open browser window", tip = "Open a new web browser window",
slot = self.openBrowserWindow, enabled = 1)
self.actionDefinitions['open_i1projects_default'] = dict(text = "View default CCP4i projects", tip = "Import and display projects from previous CCP4 interface",
slot = self.openI1Projects, enabled = 1)
self.actionDefinitions['open_i1projects_select'] = dict(text = "View selected CCP4i projects", tip = "Import and display projects from previous CCP4 interface",
slot = functools.partial(self.openI1Projects, 'select'), enabled = 1)
self.actionDefinitions['back'] = dict(text = "Back", tip = "Go back one page",
slot = self.historyBack, enabled = 1)
self.actionDefinitions['forward'] = dict(text = "Forward",tip = "Go forward one page",
slot = self.historyForward, enabled = 1)
self.actionDefinitions['reload'] = dict(text = "Reload",tip = "Reload current page",
slot = self.reloadPage, shortcut = "Ctrl+R", enabled = 1)
self.actionDefinitions['listProcesses'] = dict(text = "Running jobs and processes", tip = "Check jobs are still running",
slot = self.listProcesses)
self.actionDefinitions['manageImportFiles'] = dict(text = "Manage imported files", tip = "Record provenance or remove imported files",
slot = self.openManageImportFiles, enabled = self.isProjectViewer)
self.actionDefinitions['manageWorkflows'] = dict(text = "Workflows", tip = "Create & manage user defined work flows",
slot = self.openWorkflow)
self.actionDefinitions['patchComFile'] = dict(text = "Task parameters and patches", tip = "Save/restore task parameters or customise a program command file",
slot = self.openPatchComFile)
self.actionDefinitions['customTask'] = dict(text = "Custom tasks", tip = "Define a task",
slot = self.openCustomTasks)
self.actionDefinitions['importJob'] = dict(text = "Import job", tip = "Report job run outside CCP4i2",
slot = self.openImportJobs)
self.actionDefinitions['programPrintLog'] = dict(text = "Program print log", tip = "Show printed diagnostic for this run of the program",
slot = functools.partial(self.openApplication,'programPrintLog'), enabled = 1)
self.actionDefinitions['programHTTPLog'] = dict(text = "HTTP server log", tip = "Show log from internal HTTP server",
slot = functools.partial(self.openApplication,'programHTTPLog'), enabled = 1)
self.actionDefinitions['editScript'] = dict(text = "Edit/run script", tip = "Edit/run Python script within CCP4i2",
slot = functools.partial(self.openApplication,'editScript'), enabled = 1)
self.actionDefinitions['sendReport'] = dict(text = "Send error report", tip = "Send error report to CCP4",
slot = self.openSendReport,enabled = self.isProjectViewer)
self.actionDefinitions['update_core'] = dict(text = "Manage CCP4 updates", tip = "Examine, apply or remove CCP4 updates",
slot = self.um.manage, enabled = self.um.is_unlocked)
self.actionDefinitions['update_gui'] = dict(text = "Update CCP4I2", tip = "Fast track update for CCP4 interface",
slot = self.openUpdate, enabled = CCP4Modules.PREFERENCES().guiUpdateEnabled)
self.actionDefinitions['import_task'] = dict(text = "Import task code", tip = "Load new task from compressed file",
slot = self.openImportTask, enabled = 1)
self.actionDefinitions['export_task'] = dict(text = "Export task", tip = "Save task to compressed file",
slot = self.openExportTask, enabled = 1)
self.actionDefinitions['list_tasks'] = dict(text = "List tasks", tip = "List tasks currently available in CCP4i2",
slot = self.listTasks, enabled = 1)
self.actionDefinitions['grab_task'] = dict(text = "Grab task widget/report", tip = "Make screenshot of current task widget or report",
slot = self.grabWidget, enabled = self.isProjectViewer)
self.setActionDefinition('compress_demo_data', dict(text = "Compress demo data", tip = "Create zip file to place on demo data download site",
slot = self.makeDemoData, enabled = 1))
self.setActionDefinition('general_project', dict(text = "Create a General project", tip = "Create a project for odds and ends",
slot = self.makeGeneralProject, enabled = 1))
self.setActionDefinition('new_project', dict(text = "New project", tip = "Create new CCP4 project",
slot = functools.partial(self.handleProjectMenu,'new_project'), enabled = 1))
self.setActionDefinition('more_projects', dict(text = "More projects..",tip = "Show all projects",
slot = functools.partial(self.handleProjectMenu,'more_projects'), enabled = 1))
self.setActionDefinition('manage_projects',dict(text = "Manage/open projects", tip = "Review, manage and open CCP4 projects",
slot = functools.partial(self.handleProjectMenu, 'manage_projects'), enabled = 1))
self.setActionDefinition('export_project',dict(text = "Export project", tip = "Save project to a compressed file",
slot = self.handleProjectMenuExport, enabled = self.isProjectViewer, icon = 'export_arrow_new'))
self.setActionDefinition('import_project',dict(text = "Import project", tip = "Load project from a compressed file",
slot = functools.partial(self.handleProjectMenu, 'import_project'), enabled = 1, icon = 'import_arrow_new'))
self.setActionDefinition('serverSetup',dict(text="Configure servers for 'remote' run jobs", tip = "Specify host and mechanism to run remote jobs",
slot = self.openServerSetup, checked = self.isServerSetupOpen))
self.setActionDefinition('redo_report',dict(text="Remake report", tip="Remake the task report",
slot=functools.partial(self.handleDeveloperTools, 'redo_report'),
enabled=self.reportAvailable))
self.setActionDefinition('view_report_source', dict(text = "View report source", tip = "Display the report in a text viewer",
slot = functools.partial(self.handleDeveloperTools, 'view_report_source'),
enabled = self.reportAvailable))
self.setActionDefinition('remake_cached_lookups', dict(text = "Remake cached lookups", tip = "Remake lookups, e.g. when a new module or datatype is added",
slot = functools.partial(self.handleDeveloperTools, 'remake_cached_lookups'),
enabled = self.isProjectViewer))
self.setActionDefinition('view_test_report', dict(text = "Show project test report", tip = "Display the report from re-running the project",
slot = functools.partial(self.handleDeveloperTools, 'view_test_report'),
enabled = self.testReportAvailable))
self.setActionDefinition('make_test_suite', dict(text="Convert project to test suite", tip="Add unittest template files",
slot=functools.partial(self.handleDeveloperTools, 'make_test_suite'),
enabled=self.isProjectViewer))
self.setActionDefinition('demo_data_info', dict(text="More info", tip="Description of downloadable demo data",
slot=functools.partial(self.showDemoDataInfo)))
self.setActionDefinition('download_demo_data', dict(text="Download data", tip="Download data from internet",
slot=functools.partial(self.downloadDemoData)))
self.setActionDefinition('auto_task_docs', dict(text="Recreate task docs index", tip="Auto generate docs/tasks/index.html",
slot=functools.partial(self.handleDeveloperTools, 'auto_task_docs')))
self.setActionDefinition('clearStatusFiles', dict(text = "Clear shutdown/restart status", tip="Remove possibly corrupt status files",
slot = functools.partial(purgeStatusFiles,0)))
def updateActionEnabled(self):
for actionName in ['print', 'run', 'find', 'save']:
ifEnabled = self.actionDefinitions[actionName]['enabled']()
action = self.findChild(QtGui.QAction,actionName)
#print 'updateActionEnabled',actionName,ifEnabled,action
if action is not None:
action.setEnabled(ifEnabled)
def actionDefinition(self, actionName=''):
return self.actionDefinitions.get(actionName,{})
def setActionDefinition(self,actionName='',actionDefinition={}):
self.actionDefinitions[actionName] = actionDefinition
def getActionDef(self,name):
return self.actionDefinitions.get(name,dict(text=name))
def openBrowserWindow(self):
b = CBrowserWindow() # KJS : Broken ?
#print 'openBrowserWindow',b,len(CBrowserWindow.Instances)
b.show()
#print 'openBrowserWindow raise_'
b.raise_()
def openI1Projects(self, mode='default'):
if mode == 'default':
self.openI1Projects1()
else:
from qtgui import CCP4FileBrowser
self.I1FileBrowser = CCP4FileBrowser.CFileDialog(self, title='Open old CCP4 project(s) from directories.def or database.def',
filters= ['Old CCP4 directory.def or database.def (*.def)'],
defaultSuffix='.def', fileMode=QtGui.QFileDialog.ExistingFile)
self.I1FileBrowser.widget.fileDialog.setFilter(QtCore.QDir.AllEntries | QtCore.QDir.Hidden | QtCore.QDir.NoDotAndDotDot)
self.connect(self.I1FileBrowser,QtCore.SIGNAL('selectFile'),self.openI1Projects1)
self.I1FileBrowser.show()
def openI1Projects1(self, fileName=None):
from qtgui import CCP4I1Projects
from core import CCP4Utils
if fileName is None:
if sys.platform == "win32":
fileName = os.path.normpath(os.path.join(CCP4Utils.getHOME(), 'CCP4', 'windows', 'directories.def'))
else:
fileName = os.path.normpath(os.path.join(CCP4Utils.getHOME(), '.CCP4', 'unix', 'directories.def'))
for pV in CCP4I1Projects.CI1ProjectViewer.Instances:
if pV.model().sourceFile == fileName:
pV.show()
pV.raise_()
return
pV = CCP4I1Projects.CI1ProjectViewer(fileName=fileName)
CCP4I1Projects.CI1ProjectViewer.Instances[-1].show()
CCP4I1Projects.CI1ProjectViewer.Instances[-1].raise_()
def toolBar(self,name):
return self.findChild(QtGui.QToolBar,name)
def openProject(self,projectId,projectName=None):
#print 'CMainWindow.openProject',projectId,projectName
from qtgui import CCP4ProjectViewer
for window in CCP4ProjectViewer.CProjectViewer.Instances:
#print 'currently open',window,window.taskFrame.openJob.projectId,type(window.taskFrame.openJob.projectId)
try:
if window.taskFrame.openJob.projectId == projectId:
window.show()
window.raise_()
return
except Exception as e:
#print 'CMainWindow.openProject error',str(e)
pass
projectDir = CCP4Modules.PROJECTSMANAGER().db().getProjectInfo(projectId=projectId,mode='projectdirectory')
if not os.path.exists(projectDir):
QtGui.QMessageBox.warning(self,'','Error in opening project '+str(projectName)+'\nProject directory does not exist:\n'+str(projectDir))
return
if not os.path.exists(os.path.join(projectDir,'CCP4_JOBS')):
QtGui.QMessageBox.warning(self,'','Error in opening project '+str(projectName)+'\nProject directory does not exist:\n'+os.path.join(projectDir,'CCP4_JOBS'))
return
p = CCP4ProjectViewer.CProjectViewer(projectId=projectId)
p.resize(CCP4ProjectViewer.DEFAULT_WINDOW_SIZE[0],CCP4ProjectViewer.DEFAULT_WINDOW_SIZE[1])
p.show()
def openWorkflow(self):
from core import CCP4WorkflowManagerGui
CCP4WorkflowManagerGui.openWorkflowManagerGui()
def openPatchComFile(self):
from core import CCP4ComFilePatchManagerGui
CCP4ComFilePatchManagerGui.openGui()
def openCustomTasks(self):
from qtgui import CCP4CustomTaskManagerGui
CCP4CustomTaskManagerGui.openGui()
def openImportJobs(self):
from qtgui import CCP4ImportedJobManagerGui
CCP4ImportedJobManagerGui.openGui()
def handleProjectMenu(self, mode=''):
from qtgui import CCP4ProjectManagerGui
#print 'handleprojectMenu',mode
if mode == 'new_project':
if CCP4ProjectManagerGui.CNewProjectGui.insts is None:
CCP4ProjectManagerGui.CNewProjectGui.insts = CCP4ProjectManagerGui.CNewProjectGui()
CCP4ProjectManagerGui.CNewProjectGui.insts.clear()
CCP4ProjectManagerGui.CNewProjectGui.insts.show() # KJS : PyDev indicating no clear/show. Investigate this.
elif mode == 'manage_projects':
if CMainWindow.projectManagerDialog is None:
CMainWindow.projectManagerDialog = CCP4ProjectManagerGui.CProjectManagerDialog()
CMainWindow.projectManagerDialog.setMode('all')
CMainWindow.projectManagerDialog.show()
CMainWindow.projectManagerDialog.raise_()
elif mode == 'more_projects':
if CMainWindow.projectManagerDialog is None:
CMainWindow.projectManagerDialog = CCP4ProjectManagerGui.CProjectManagerDialog()
CMainWindow.projectManagerDialog.setMode('open')
CMainWindow.projectManagerDialog.show()
CMainWindow.projectManagerDialog.raise_()
elif mode == 'import_project':
if CMainWindow.projectManagerDialog is None:
CMainWindow.projectManagerDialog = CCP4ProjectManagerGui.CProjectManagerDialog()
CMainWindow.projectManagerDialog.hide()
CMainWindow.projectManagerDialog.handleImportProject()
elif mode == 'general_project':
self.makeGeneralProject()
def makeGeneralProject(self):
from core import CCP4Utils
name = 'General'
status = CCP4Modules.PROJECTSMANAGER().projectStatus(name)
if status == 0:
QtGui.QMessageBox.information(self,'General project exists','General project already exists - use Project menu to open it')
return
elif status != 1:
# Its in the database but broken in some way..
QtGui.QMessageBox.warning(self,'General project exists','General project exists but may be corrupted - use Manage Projects tool from the Projects menu')
return
else:
directory = os.path.join(CCP4Utils.getHOME(),'CCP4_General_Project')
print 'Making General Project in directory:',directory
try:
projectId = CCP4Modules.PROJECTSMANAGER().createProject(projectName=name,projectPath=directory)
except CException as e:
e.warningMessage()
return
except:
QtGui.QMessageBox.warning(self, 'Error creating project', 'Unknown error creating project')
return
else:
QtGui.QMessageBox.information(self, 'General project created', 'General project created in directory\n' + directory)
self.openProject(projectName='General')
def openPreferences(self):
if self.preferenceWindow is None:
from qtgui import CCP4PreferencesGui
self.preferenceWindow = CCP4PreferencesGui.CPreferencesWindow(self)
#print 'CMainWindow.openPreferences',self.preferenceWindow
self.preferenceWindow.show()
self.preferenceWindow.raise_()
def isPreferencesOpen(self):
if self.preferenceWindow is not None and self.preferenceWindow.isVisible():
return True
else:
return False
def openServerSetup(self):
if getattr(self,'serverSetupWindow',None) is None:
from qtgui import CCP4JobControlGui
self.serverSetupWindow = CCP4JobControlGui.CServerSetupWindow(self)
#print 'CMainWindow.openPreferences',self.preferenceWindow
self.serverSetupWindow.show()
self.serverSetupWindow.raise_()
def isServerSetupOpen(self):
if getattr(self,'serverSetupWindow',None) is not None and self.serverSetupWindow.isVisible():
return True
else:
return False
def openConfig(self):
if self.configWindow is None:
from core import CCP4ConfigGui
self.configWindow = CCP4ConfigGui.CConfigWindow(self)
#print 'CMainWindow.openConfig',self.configWindow
self.configWindow.show()
self.configWindow.raise_()
def isConfigOpen(self):
if self.configWindow is not None and self.configWindow.isVisible():
return True
else:
return False
def openFileDialog(self):
from qtgui import CCP4FileBrowser
filter_list = []
mimeTypeHandler = CCP4Modules.MIMETYPESHANDLER()
if self.fileDialog is None:
filter_list.append('All files (*.*)')
self.fileDialog = CCP4FileBrowser.CFileDialog(self, title='Open file', filters=filter_list, addAll=False)
self.connect(self.fileDialog, QtCore.SIGNAL('selectFile'), self.handleOpenFileSelection)
self.fileDialog.show()
def handleOpenFileSelection(self, fileName=''):
#print 'CCP4BrowserWindow.handleOpenFileSelection',fileName
if isinstance(self, CBrowserWindow):
self.openFile(fileName, internal=True)
else:
OPENFILE(fileName)
def handleDeveloperTools(self,mode):
#print 'handleDeveloperTools',mode
if mode == 'redo_report':
self.redoReport()
elif mode == 'view_report_source':
try:
openJob = self.taskFrame.openJob
except:
return
fileName = CCP4Modules.PROJECTSMANAGER().makeFileName(jobId=openJob.jobId,mode='REPORT')
if os.path.exists(fileName):
CCP4Modules.WEBBROWSER().openFile(fileName=fileName,format='text/plain')
elif mode == 'remake_cached_lookups':
try:
from core.CCP4Modules import TASKMANAGER, PIXMAPMANAGER
from core.CCP4DataManager import DATAMANAGER
print "Off to remake CTaskManager cache..."
TASKMANAGER().buildLookupFromScratch()
print "...Completed"
print "Off to remake CDataManager cache..."
DATAMANAGER().buildClassLookupFromScratch()
print "...Completed"
print "Off to remake CPixmapManager cache..."
PIXMAPMANAGER().buildCacheFromScratch()
print "...Completed"
except:
print "Failed to remake caches"
elif mode == 'view_test_report':
testReportList = glob.glob(os.path.join(CCP4Modules.PROJECTSMANAGER().db().getProjectInfo(projectId=self.openJob.projectId,mode='projectdirectory'),'CCP4_test*.log'))
if len(testReportList) > 0:
CCP4Modules.WEBBROWSER().openFile(fileName=testReportList[0])
return
elif mode == 'make_test_suite':
from core import CCP4ProjectBasedTesting
testBuilder = CCP4ProjectBasedTesting.BuildTestSuite(projectId=self.getProject())
rv = testBuilder.run()
if rv.maxSeverity() > SEVERITY_WARNING:
rv.warningMessage(parent=self,windowTitle=self.windowTitle(),message='Error converting project to test suite')
else:
builder = CCP4ProjectBasedTesting.BuildTestSuite(projectId=self.getProject())
try:
err = builder.run()
except:
err.warningMessage()
else:
projDir = CCP4Modules.PROJECTSMANAGER().db().getProjectDirectory(projectId=self.getProject())
self.testSuiteDialog = QtGui.QDialog(self)
self.testSuiteDialog.setWindowTitle('Creating a test suite')
self.testSuiteDialog.setLayout(QtGui.QVBoxLayout())
label = QtGui.QLabel("""A directory for test definitions has been created at\n""" +
str(projDir)+'/CCP4_TEST_SYSTEM\n' +
"""You should edit in your tests and then 'Export' this project from 'Manage Projects'\n""" +
"""You can then run the test with 'testi2sys exported_file_path'""", self)
self.testSuiteDialog.layout().addWidget(label)
self.testSuiteDialog.show()
self.testSuiteDialog.raise_()
elif mode == 'auto_task_docs':
from core import CCP4TaskManager
rv = CCP4TaskManager.CMakeDocsIndex().run()
if rv.maxSeverity() > SEVERITY_WARNING:
rv.warningMessage(parent=self,windowTitle=self.windowTitle(),message='Error recreating task documentation index page')
def listTasks(self):
import tempfile
from core import CCP4TaskManager
from core import CCP4Utils
text = CCP4TaskManager.LISTTASKS(ifPrint=False)
fileName = tempfile.mktemp(suffix='.txt')
CCP4Utils.saveFile(fileName,text)
widget = CCP4Modules.WEBBROWSER().openFile(fileName)
widget.setFont(style='fixed_width')
def openExportTask(self):
from core import CCP4Utils
import zipfile
dirPath = QtGui.QFileDialog.getExistingDirectory(self,'Select pipeline directory to save as task compressed file',os.path.join(CCP4Utils.getCCP4I2Dir(),'pipelines')).__str__()
if not os.path.isdir(dirPath):
return
if not os.path.relpath(dirPath,CCP4Utils.getCCP4I2Dir()).startswith('pipelines'):
err = CException(self.__class__,209,dirPath)
err.warningMessage(parent=self,windowTitle='Error creating compressed task file',message='Selected directory is not a pipeline in the currently running cccp4i2')
return
zipPath = dirPath + '.ccp4i2task.zip'
if os.path.exists(zipPath):
query = QtGui.QMessageBox.question(self,'Overwrite task compressed file?','Overwrite existing'+zipPath+'?',QtGui.QMessageBox.Cancel|QtGui.QMessageBox.Yes)
if query == QtGui.QMessageBox.Cancel:
return
else:
os.remove(zipPath)
try:
zip = zipfile.ZipFile(zipPath, mode='w')
except:
err = CException(self.__class__, 201, zipPath)
err.warningMessage(parent=self,windowTitle='Error creating compressed task file',message='Creating'+str(zipPath))
return
try:
CCP4Utils.zipDirectory(zip,dirPath,rootRelPath=CCP4Utils.getCCP4I2Dir())
except:
err = CException(self.__class__, 202, 'Saving', dirPath, 'to', zipPath)
err.warningMessage(parent=self,windowTitle='Error creating compressed task file',message='Saving'+str(dirPath))
return
try:
zip.close()
except:
return CErrorReport(self.__class__,203,zipPath)
err.warningMessage(parent=self,windowTitle='Error creating compressed task file',message='Closing'+str(zipPath))
return # KJS : Ok, wtf is this ? <^
info = QtGui.QMessageBox.information(self,'Saved compressed task file','Task saved to'+str(zipPath))
def openImportTask(self):
import shutil
import zipfile
from core import CCP4Utils
filePath = QtGui.QFileDialog.getOpenFileName(self,'Select compressed file containing task','',"Compressed task (*.ccp4i2task.zip)").__str__()
if not os.path.isfile(filePath): return
try:
zip = zipfile.ZipFile(filePath,mode='r')
except:
err = CException(self.__class__,204,filePath)
err.warningMessage(parent=self,windowTitle='Error reading compressed task file',message='Reading '+str(filePath))
return
targetPath = CCP4Utils.getCCP4I2Dir()
err= CException()
for zinfo in zip.infolist():
if not zinfo.filename.startswith('pipelines'):
err.append(self.__class__,206,str(zinfo.filename))
else:
if os.path.exists(os.path.join(targetPath,zinfo.filename)):
overwrite = QtGui.QMessageBox.question(self,'Overwrite existing task?','Overwrite existing '+str(zinfo.filename)+'?',QtGui.QMessageBox.Cancel|QtGui.QMessageBox.Yes)
if overwrite == QtGui.QMessageBox.Cancel:
err.append(self.__class__,207,zinfo.filename)
break
else:
try:
shutil.rmtree(os.path.join(targetPath,zinfo.filename))
except:
err.append(self.__class__,208,os.path.join(targetPath,zinfo.filename))
break
try:
zip.extract(zinfo,targetPath)
except:
err.append(self.__class__,205,filePath)
zip.close()
if len(err) > 0:
err.warningMessage(parent=self,windowTitle='Error reading compressed task file',message='Extracting from '+str(filePath)+' to '+str(targetPath))
return
info = QtGui.QMessageBox.information(self,'New task installed','New '+ zinfo.filename+ ' task installed - Please restart CCP4i2')
def showAbout(self):
if not hasattr(self,'aboutDialog'):
from core import CCP4Utils
self.aboutDialog = QtGui.QDialog(self)
self.aboutDialog.setLayout(QtGui.QVBoxLayout())
self.aboutDialog.layout().setContentsMargins(1,1,1,1)
#self.aboutDialog.layout().setSpacing(1)
self.aboutDialog.setWindowTitle('About CCP4i2')
topWidget = QtGui.QWidget()
topWidget.setLayout(QtGui.QHBoxLayout())
topWidget.setStyleSheet("QWidget { background-color:white; }")
label = QtGui.QLabel(self)
fileName = os.path.normpath(os.path.join(CCP4Utils.getCCP4I2Dir(),'qticons','ccp4.png'))
label.setPixmap(QtGui.QPixmap(fileName))
topWidget.layout().addWidget(label)
topRightWidget = QtGui.QWidget()
topRightWidget.setLayout(QtGui.QVBoxLayout())
label = QtGui.QLabel('CCP4i2',self)
label.setStyleSheet("QLabel { font-size: 24px; font-weight: bold; }")
topRightWidget.layout().addWidget(label)
topWidget.layout().addWidget(topRightWidget)
self.aboutDialog.layout().addWidget(topWidget)
version = CCP4Utils.getProgramVersion('ccp4i2')
date = CCP4Utils.getProgramVersion('ccp4i2',mode='date')
label = QtGui.QLabel('Version '+version+' built on '+date+"\n"+'User interface to CCP4 Program Suite version '+ CCP4Utils.getProgramVersion('ccp4'),self)
label.setStyleSheet("QLabel { font-size: 14px; font-style: italic; font-weight: bold; }")
topRightWidget.layout().addWidget(label)
label = QtGui.QLabel(self)
label.setText('Copyright (C) 2001-2008 University of York, CCLRC\n' +
'Copyright (C) 2009-2010 University of York\n' +
'Copyright (C) 2011-2015 Science & Technology Facilities Council')
bottomWidget = QtGui.QWidget()
bottomWidget.setLayout(QtGui.QHBoxLayout())
bottomWidget.layout().addWidget(label)
self.aboutDialog.layout().addWidget(bottomWidget)
self.aboutDialog.show()
self.aboutDialog.raise_()
def showDemoDataInfo(self):
from core import CCP4Utils
CCP4Modules.WEBBROWSER().loadWebPage(CCP4Modules.DEMODATAMANAGER().getOverviewPage())
def downloadDemoData(self):
CCP4Modules.DEMODATAMANAGER().downloadDemoData(self)
def getProject(self):
return None
def isProjectViewer(self):
return (self.getProject() is not None)
def isNotProjectViewer(self):
return True
def reportAvailable(self):
return False
def testReportAvailable(self):
return False
def grabWidget(self):
# Dummy method reimplemented in CProjectViewer
pass
def makeDemoData(self):
CCP4Modules.DEMODATAMANAGER().makeDemoData(parentWidget=self)
def listProcesses(self):
CCP4Modules.JOBCONTROLLER().listLocalProcesses()
from qtgui import CCP4JobControlGui
if getattr(self,'listProcessesWindow',None) is None:
self.listProcessesWindow = CCP4JobControlGui.CListProcesses(self)
self.listProcessesWindow.load()
self.listProcessesWindow.show()
self.listProcessesWindow.raise_()
class CBrowserWindow(CMainWindow):
ERROR_CODES = {100 : {'description' : 'Invalid file name'}}
Instances = set()
Dummy = None
def __init__(self, parent=None, welcome=True):
self.stack = None
CMainWindow.__init__(self,parent)
self.setWindowTitle(self.version)
CBrowserWindow.Instances.add(self)
self.stack = QtGui.QStackedWidget(self)
#print 'CBrowserWindow.__init__ parent',self,parent,CBrowserWindow.Instances
self.setCentralWidget(self.stack)
self.connect(self,QtCore.SIGNAL("destroyed(QObject*)"),CBrowserWindow.updateInstances)
self.factory = None
QtWebKit.QWebSettings.globalSettings().setAttribute(QtWebKit.QWebSettings.PluginsEnabled, True)
# Create menu and tool bar and add the 'general' actions
self.mainToolBar = CToolBar(self,'main','Main toolbar')
self.fileToolBar = CToolBar(self,'file','File')
self.addToolBar(self.mainToolBar)
self.addToolBarBreak()
self.addToolBar(self.fileToolBar)
if self.mainToolBar is not None:
self.mainToolBar.extend(['help_ccp4i2','open','back','forward','reload','find'])
self.mini = False
self.setTab('nocontext')
self.editSplitter = CEditSplitter(self)
self.connect(self.editSplitter.addressEdit,QtCore.SIGNAL("returnPressed()"),self.addressEdited)
self.connect(self.editSplitter.searchEdit,QtCore.SIGNAL("returnPressed()"),self.searchEdited)
self.toolBar('file').addWidget(self.editSplitter)
self.setHistoryActionAvailability()
self.connect(self.tab(),QtCore.SIGNAL("currentChanged(int)"),self.setTabTitles)
sb = self.statusBar()
self.searchEngineString = "http://www.google.com/search?q="
self.drawFindTool()
self.defaultSizePolicy = [self.sizePolicy().horizontalPolicy(),self.sizePolicy().verticalPolicy()]
if welcome: self.loadWebPage(helpFileName='welcome.html',newTab=True)
self.resize(800,800)
@staticmethod
def updateInstances(qobj):
CBrowserWindow.Instances = set([window for window in CBrowserWindow.Instances if isAlive(window)])
#print 'webbrowser.updateInstances',CBrowserWindow.Instances
def close(self):
#Close any widgets in tabs - mostly out of concern for watched files
for indx in range(self.tab().count()): self.tab().widget(indx).close()
CMainWindow.close(self)
def setMini(self,mode=True):
self.mini = mode
tabs = self.findChildren(CTabWidget)
if self.mini:
self.mainToolBar.hide()
self.fileToolBar.hide()
self.resize(500,300)
self.layout().setContentsMargins(0,0,0,0)
self.layout().setSpacing(0)
for tab in tabs:
tab.cornerWidget().setText('Expand window')
else:
self.mainToolBar.show()
self.fileToolBar.show()
self.resize(800,800)
for tab in tabs:
tab.cornerWidget().setText('Close tab')
def positionOver(self,widget):
geom = widget.geometry()
globalPos = widget.mapToGlobal(QtCore.QPoint(geom.x(),geom.y()))
self.move(globalPos)
def downloadTestData(self,**kw):
pass
def drawFindTool(self):
self.findFrame = CFindFrame(self)
self.findDock = QtGui.QDockWidget('Find',self)
self.findDock.setWidget(self.findFrame)
self.findDock.setAllowedAreas(QtCore.Qt.TopDockWidgetArea|QtCore.Qt.BottomDockWidgetArea)
self.findDock.setTitleBarWidget(None)
self.addDockWidget(QtCore.Qt.BottomDockWidgetArea,self.findDock,QtCore.Qt.Horizontal)
self.findDock.close()
self.connect(self.findFrame,QtCore.SIGNAL('findNext'),self.handleFindNext)
self.connect(self.findFrame,QtCore.SIGNAL('findPrevious'),self.handleFindPrevious)
self.connect(self.findFrame,QtCore.SIGNAL('highlightAll'),self.handleFindHighlightAll)
def StatusBarMessage(self,message=None):
sb = self.statusBar()
sb.showMessage(message)
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):
#print 'setTabTitles',title
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(self.version+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.editSplitter.addressEdit.setText(widget.url().toString())
self.setHistoryActionAvailability()
def tab(self):
# Returns the CTabWidget for the current context (ie project)
if self.stack is None:
return None
return self.stack.currentWidget()
def contextTab(self,context):
for indx in range(self.stack.count()):
if str(self.stack.widget(indx).objectName()) == context:
return self.stack.widget(indx)
return None
def setTab(self,context):
tab = self.stack.currentWidget()
if tab is not None and str(tab.objectName()) == context:
return
for indx in range(self.stack.count()):
if str(self.stack.widget(indx).objectName()) == context:
self.stack.setCurrentIndex(indx)
return
tab = CTabWidget(self,name=context,mini=self.mini)
self.connect(tab.cornerWidget(),QtCore.SIGNAL("clicked(bool)"),self.handleTabCornerWidget)
indx = self.stack.addWidget(tab)
self.stack.setCurrentIndex(indx)
#print 'setTab new',indx,tab,context
#-------------------------------------------------------------------
def newTab(self, widget=None, title=None, context='nocontext', toolTip=None, icon=None, copen=True):
#-------------------------------------------------------------------
if title is None:
title = widget.title()
#print 'CWebBrowser.newTab title',widget,title
if icon is not None:
idx = self.tab().addTab(widget,icon,title)
else:
idx = self.tab().addTab(widget,QtCore.QString(title))
if toolTip is not None:
self.tab().setTabToolTip(idx,toolTip)
#if colour: self.tab().setTabTextColor(QtGui.QColor(colour))
if copen:
self.setTabIndex(idx)
self.editSplitter.addressEdit.setText(title)
self.tab().repaint()
return idx
def handleTabCornerWidget(self,clickBool = None):
if self.mini:
self.setMini(False)
else:
self.deleteTab()
#-------------------------------------------------------------------
def deleteTab(self, ok=False):
#-------------------------------------------------------------------
if self.tab().count() > 1:
indx = self.tab().currentIndex()
self.tab().deleteTabWidget(indx)
self.setHistoryActionAvailability()
def tabWidgets(self):
widgets = []
for idx in range(0,self.tab().count()):
widgets.append(self.tab().widget(idx))
return widgets
#-------------------------------------------------------------------
def setTabIndex(self, index=-1, fileName=''):
#-------------------------------------------------------------------
if fileName and index < 0:
index = self.fileOpenInTab(fileName)
if index >= 0 and index <= self.tab().count():
self.tab().setCurrentIndex(index)
self.setWindowTitle(self.version+self.tab().widget(index).objectName())
#-------------------------------------------------------------------
def fileOpenInTab(self, fileName):
#-------------------------------------------------------------------
for idx in range(0,self.tab().count()):
if str(self.tab().tabText(idx)) == fileName:
return idx
fileName = os.path.abspath(str(fileName))
for idx in range(0,self.tab().count()):
if self.tab().widget(idx).fileName == fileName:
return idx
return -1
def CustomMimeTypeRequested(self, url=None):
#print 'CWebBrowser.CustomMimeTypeRequested',url.path(),url.scheme()
if url is not None and url.scheme() == 'file':
path = str(url.path())
if os.path.exists(path):
self.openFile(path, internal=True)
elif os.path.splitext(path)[1] == '.i2com':
com = os.path.split(os.path.splitext(path)[0])[1]
#print 'CustomMimeTypeRequested i2com',com
action = self.findChild(QtGui.QAction,com)
if action is not None:
action.trigger()
elif self.actionDefinitions.has_key(com) and self.actionDefinitions[com].has_key('slot'):
#print 'CustomMimeTypeRequested try',self.actionDefinitions[com]['slot']
try:
self.actionDefinitions[com]['slot']()
except:
pass
#-------------------------------------------------------------------
def openApplication(self, application=None):
#-------------------------------------------------------------------
from qtgui import CCP4TextViewer
from qtgui import CCP4ErrorReportViewer
widget = None
application = str(application)
idx = self.fileOpenInTab(application)
#print 'openApplication',application,idx
if idx >= 0:
self.tab().setCurrentIndex(idx)
#self.tab().widget(idx).open(self.tab().widget(idx).filename)
return self.tab().widget(idx)
if application == 'programPrintLog':
widget = CCP4ErrorReportViewer.CPrintLogViewer(self)
#print 'CWebBrowser.openApplication',widget
widget.openThread(thread='main_thread')
title = 'Program print log'
elif application == 'programHTTPLog':
widget = CCP4ErrorReportViewer.CPrintLogViewer(self)
#print 'CWebBrowser.openApplication',widget
widget.openThread(thread='HTTPServer')
title = 'Program print log'
elif application == 'editScript':
widget = CCP4TextViewer.CScriptViewer(self)
widget.open()
title= 'Edit script'
if widget is not None:
widget.setObjectName(title)
self.newTab(widget,title)
widget.show()
return widget
#-------------------------------------------------------------------
def openFile(self, fileName=None, format=None, title=None, toFront=False, internal=False):
#-------------------------------------------------------------------
from core import CCP4Config
# Is the file already displayed - force a redraw
if fileName is None or fileName=='None':
return None
fileName = str(fileName)
idx = self.fileOpenInTab(fileName)
if idx >= 0:
if self.tab().widget(idx).isFileModified():
self.tab().widget(idx).reload()
self.tab().setCurrentIndex(idx)
if toFront: self.raise_()
return self.tab().widget(idx)
mimeTypeHandler = CCP4Modules.MIMETYPESHANDLER()
#print "CCP4WebBrowser.open fileName",fileName,format,mimeTypeHandler,title
if not os.path.exists(fileName):
QtGui.QMessageBox.warning(self,self.windowTitle(),'File does not exist \n'+fileName)
return None
if os.path.isdir(fileName):
format = 'dir'
# If format not recognised try if file extension is recognised
if mimeTypeHandler is None and format is None:
# No handler so just throw it at web browser and hope
format = 'text/html'
else:
if format is not None and not mimeTypeHandler.isSupportedFormat(format):
format = None
if format is None:
format = mimeTypeHandler.formatFromFileExt(fileName)
if format is None:
format = 'text/html'
#print 'CCP4WebBrowser.openFile format',format
# If its a plugin format launch the plugin
if ['text/html'].count(format):
widget = self.loadWebPage(fileName,newTab=True)
elif mimeTypeHandler.useDesktopServices(format):
abs_fileName = os.path.abspath(fileName)
#print 'calling QDesktopServices',abs_fileName
url = QtCore.QUrl.fromLocalFile(abs_fileName)
rv = QtGui.QDesktopServices.openUrl(url)
if not rv:
QtGui.QMessageBox.warning(None,self.windowTitle(),'Attempting to display file '+os.path.split(abs_fileName)[-1]+'\nusing desktop services failed')
#.. and close this window if nothing else is displayed
if not internal and self.stack.count() == 1:
self.close()
return None
else:
widgetClassList = mimeTypeHandler.getViewers(format)
widgetClass = widgetClassList[0]
if len(widgetClassList) == 0:
QtGui.QMessageBox.warning(None,self.windowTitle(),'Sorry no way to display file type: '+format)
return None
else:
#widgetClass = widgetClassList[0]
# PhilE hack to display non-MTZ files as text
root, ext = os.path.splitext(str(fileName))
if ext != '.mtz':
widgetClass = mimeTypeHandler.getViewers("text/plain")[0]
if isinstance(widgetClass,str):
# This is a keyword for the launcher
CCP4Modules.LAUNCHER().openInViewer(viewer=widgetClass,fileName=fileName)
return None
if CCP4Config.DEVELOPER():
widget = widgetClass(self)
else:
try:
widget = widgetClass(self)
except:
QtGui.QMessageBox.warning(None,self.windowTitle(),'Error opening display for file type: '+format)
return None
#print 'CWebBrowser.openFile',widget
if CCP4Config.DEVELOPER():
rv = widget.open(fileName=fileName)
else:
try:
rv = widget.open(fileName=fileName)
except CException as e:
widget.close()
e.warningMessage(windowTitle=self.windowTitle())
except:
widget.close()
QtGui.QMessageBox.warning(None,self.windowTitle(),'Attempting to display file '+os.path.split(fileName)[-1]+'\n as '+format+' failed.\n')
return None
if title is None:
title = widget.title()
self.newTab(widget,title)
widget.show()
#print 'openFile size',widget.height(),widget.width()
if toFront: self.raise_()
return widget
def reloadFile(self,fileName):
# Beware this is used as slot by CCP4ProjectManagerGui so arguments are fixed
#print 'WEBBROWSER.reloadFile',fileName
if fileName is None or fileName=='None':
return None
fileName = str(fileName)
idx = self.fileOpenInTab(fileName)
if idx >= 0:
if self.tab().widget(idx).isFileModified():
self.tab().widget(idx).reload()
self.tab().setCurrentIndex(idx)
#if toFront: self.raise_()
return self.tab().widget(idx)
else:
return None
def showHelp(self,mode='ccp4i2'):
#print 'showHelp',mode
from core import CCP4Utils
if mode == 'ccp4i2':
self.loadWebPage(helpFileName='welcome.html', newTab=True)
elif mode == 'quickstart':
self.loadWebPage(helpFileName='quickstart/index.html', newTab=True)
elif mode == 'quickexpert':
self.loadWebPage(helpFileName='quickexpert/index.html', newTab=True)
elif mode == 'youtube':
rv = QtGui.QDesktopServices.openUrl(QtCore.QUrl('https://www.youtube.com/watch?v=fB7BRVzBURg'))
elif mode == 'task_docs':
self.loadWebPage(helpFileName=os.path.join(CCP4Utils.getCCP4I2Dir(), 'docs', 'tasks', 'index.html'), newTab=True)
elif mode == 'tutorial':
self.loadWebPage(helpFileName='tutorial.html', newTab=True)
elif mode == 'ccp4_home':
url = QtCore.QUrl("http://www.ccp4.ac.uk")
self.loadPage(url, newTab=True)
elif mode == 'updates':
url = QtCore.QUrl("http://www.ccp4.ac.uk/updates")
self.loadPage(url, newTab=True)
elif mode == 'license':
self.loadWebPage(helpFileName='general/license.html', newTab=True)
def loadWebPage(self, fileName=None, helpFileName=None, target=None, newTab=0):
from core import CCP4Utils
#print 'loadWebPage',fileName,helpFileName,target
if fileName is not None:
if target is None and fileName.count('#'):
fileName, target = fileName.split('#', 1)
elif helpFileName is not None:
if target is None and helpFileName.count('#'):
helpFileName, target = helpFileName.split('#', 1)
if os.path.splitext(helpFileName)[1] == '':
helpFileName = helpFileName + '.html'
if os.path.exists(helpFileName):
fileName = helpFileName
else:
docDir = os.path.join(CCP4Utils.getCCP4I2Dir(), 'docs')
fileName = os.path.join(docDir, helpFileName)
idx = 0
subDirList = ['general', 'developers', 'tasks']
while not os.path.exists(fileName) and idx < len(subDirList):
fileName = os.path.join(docDir, subDirList[idx], helpFileName)
idx += 1
if idx > len(subDirList):
return None
if target is not None:
if target[0] != '#':
target = '#' + target
else:
target = ''
if os.path.exists(fileName):
url = QtCore.QUrl.fromLocalFile(os.path.abspath(fileName))
if len(target) > 1:
url.setFragment(target[1:])
#url = QtCore.QUrl(fileName+target)
elif not fileName[0:4] == 'http':
url = QtCore.QUrl("http://" + fileName)
else:
#url = QtCore.QUrl(file)
url = file
return self.loadPage(url, newTab=newTab)
def loadPage(self, url, newTab=0):
#print 'CWebBrowser.loadPage', url.scheme(), url.path().toAscii()
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)
#print 'loadPage file',target
if not url.isValid():
err = CException(self.__class__, 100, url.path().toAscii())
err.warningMessage()
return
#print "CWebBrowser.loadPage trying", url.path(), target
if self.tab().count() > 0:
widget = self.tab().currentWidget()
else:
widget= None
#print 'CWebBrowser.loadPage', url.isValid(), widget, newTab
if not newTab and isinstance(widget, CCP4WebView.CWebView):
try:
widget.setTarget(target)
widget.load(url)
#print 'CWebBrowser.loadPage widget.loaded'
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 None
return widget
else:
view = CCP4WebView.CWebView()
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)
view.load(url)
view.setTarget(target)
#self.connect(view, QtCore.SIGNAL("linkClicked(const QUrl &)"), self.handleLinkClick)
'''
# This is now done in CWebView
if self.factory is None:
#Create Qt web plugin factory
try:
from qtgui import CCP4WebPluginFactory
self.factory = CCP4WebPluginFactory.CWebPluginFactory(view)
except:
print 'CCP4WebBrowser Error creating web plugin factory'
if self.factory is not None:
view.page().setPluginFactory(self.factory)
'''
self.newTab(view, str(view.title()))
return view
def loadViaHTTP(self, fileName=None, target=None):
from core import CCP4Utils
relPath = os.path.relpath(fileName, os.path.join(CCP4Utils.getCCP4I2Dir(), 'docs'))
#print 'loadViaHTTP',relPath
url = QtCore.QUrl('http://127.0.0.1:43434/' + relPath + '#' + target)
#print 'loadViaHTTP fragment',url.fragment()
self.loadPage(url, True)
def handleLinkClick(self, url):
#print 'CCP4BrowserWindow.handleLinkClick',url
pass
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 searchEdited(self):
text = self.editSplitter.searchEdit.text().replace(QtCore.QRegExp("\\s+"), QtCore.QString("+"))
#print 'QWebBrowser.searchEdited', text
self.loadPage(QtCore.QUrl(self.searchEngineString + str(text)))
def addressEdited(self):
text = str(self.editSplitter.addressEdit.text())
if os.path.exists(text.split('#')[0]):
self.openFile(fileName=text, internal=True)
else:
self.loadPage(QtCore.QUrl(self.editSplitter.addressEdit.text()))
def setHistoryActionAvailability(self):
widget = self.tab().currentWidget()
forwardAction = self.findChild(QtGui.QAction, 'forward')
backAction = self.findChild(QtGui.QAction, 'back')
if hasattr(widget,"history") and callable(widget.history):
history = widget.history()
#print 'setHistoryActionAvailability', backAction, history.canGoBack()
if forwardAction:
if history.canGoForward():
forwardAction.setEnabled(True)
else:
forwardAction.setEnabled(False)
if backAction:
if history.canGoBack():
backAction.setEnabled(True)
else:
backAction.setEnabled(False)
else:
# No notion of history so set actions disabled
if forwardAction:
forwardAction.setEnabled(False)
if backAction:
backAction.setEnabled(False)
def historyForward(self):
widget = self.tab().currentWidget()
if widget and 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 widget and hasattr(widget, "history") and callable(widget.history):
history = widget.history()
if history.canGoBack():
history.goToItem(history.backItem())
self.setHistoryActionAvailability()
def reloadPage(self):
widget = self.tab().currentWidget()
if widget is None:
return
if hasattr(widget, "history") and callable(widget.history):
#print 'QWebBrowser.reloadPage'
widget.history().goToItem(widget.history().currentItem())
#-------------------------------------------------------------------
def currentWidget(self):
#-------------------------------------------------------------------
if self.tab() is None:
return None
idx = self.tab().currentIndex()
if idx < 0:
return None
return self.tab().widget(idx)
#-------------------------------------------------------------------
def widgetIsRunable(self):
#-------------------------------------------------------------------
w = self.currentWidget()
if w is not None:
return w.isRunable()
else:
return False
#-------------------------------------------------------------------
def widgetIsSaveable(self):
#-------------------------------------------------------------------
w = self.currentWidget()
if w is not None:
return w.isSaveable()
else:
return False
#-------------------------------------------------------------------
def widgetIsPrintable(self):
#-------------------------------------------------------------------
w = self.currentWidget()
if w is not None:
return w.isPrintable()
else:
return False
#-------------------------------------------------------------------
def widgetIsSearchable(self):
#-------------------------------------------------------------------
w = self.currentWidget()
if w is not None:
return w.isSearchable()
else:
return False
#-------------------------------------------------------------------
def widgetIsScaleable(self):
#-------------------------------------------------------------------
w = self.currentWidget()
if w is not None:
return w.isScaleable()
else:
return None
#-------------------------------------------------------------------
def isCurrentWidget(self, mode='text'):
#-------------------------------------------------------------------
widget = self.currentWidget()
if widget is None:
return 0
if mode=='text':
from qtgui import CCP4TextViewer
if isinstance(widget, CCP4TextViewer.CTextViewer):
return 1
else:
return 0
if mode=='image':
from qtgui import CCP4ImageViewer
if isinstance(widget, CCP4ImageViewer.CImageViewer):
return 1
else:
return 0
else:
return 0
#-------------------------------------------------------------------
def handlePrint(self):
#-------------------------------------------------------------------
idx = self.tab().currentIndex()
if idx < 0:
return
printer = QtGui.QPrinter()
pd = QtGui.QPrintDialog(printer)
pdret = pd.exec_()
if pdret == QtGui.QDialog.Accepted:
painter = QtGui.QPainter()
painter.begin(printer)
self.tab().widget(idx).Print(painter)
painter.end()
#-------------------------------------------------------------------
def handleSave(self):
#-------------------------------------------------------------------
from qtgui import CCP4FileBrowser
widget = self.currentWidget()
if widget is None:
return
defaultSuffix = ''
filter_list = []
ext_list = widget.getFileExt()
if ext_list:
defaultSuffix = ext_list[0]
ext_text = ''
for ext in widget.getFileExt():
ext_text = ext_text + '*.' + ext + ' '
if ext_text:
filter_list.append(widget.getLabel() + ' (' + ext_text + ')')
self.saveWidget = CCP4FileBrowser.CFileDialog(self, title='Save ' + widget.objectName(), filters=filter_list, defaultSuffix=defaultSuffix, fileMode=QtGui.QFileDialog.AnyFile)
self.connect(self.saveWidget, QtCore.SIGNAL('selectFile'), self.currentWidget().Save)
self.saveWidget.show()
def handleRun(self):
widget = self.currentWidget()
if widget is None:
return
widget.run()
#-------------------------------------------------------------------
def openFind(self):
#-------------------------------------------------------------------
if self.findDock.isVisible():
self.findDock.setVisible(0)
else:
self.findDock.setVisible(1)
#-------------------------------------------------------------------
def isFindFrameOpen(self):
#-------------------------------------------------------------------
if self.findFrame is not None and self.findFrame.isVisible():
return 1
return 0
#-------------------------------------------------------------------
def handleFind(self, direction=1):
#-------------------------------------------------------------------
widget=self.currentWidget()
if widget is None or not widget.isSearchable():
return
text = self.findFrame.text()
#print 'CCP4WebBrowser.handleFind',text,direction
rv = widget.findText(subString=text, direction=direction, caseSensitive=self.findFrame.caseSensitive(),
wrapAroundDocument=self.findFrame.wrapAroundDocument() )
#-------------------------------------------------------------------
def handleFindNext(self):
#-------------------------------------------------------------------
self.handleFind(1)
#-------------------------------------------------------------------
def handleFindPrevious(self):
#-------------------------------------------------------------------
self.handleFind(-1)
#-------------------------------------------------------------------
def handleFindHighlightAll(self):
#-------------------------------------------------------------------
widget=self.currentWidget()
if widget is None or not widget.isSearchable():
return
text = self.findFrame.text()
rv = widget.findText(subString=text, highlightAll=1)
def setFixedWidth(self, width=0):
if width <= 0:
self.setMaximumWidth(16777215)
self.setMinimumWidth(0)
else:
self.setMaximumWidth(width + 10)
self.setMinimumWidth(width + 10)
def moveEvent(self, event):
delta = event.pos()-event.oldPos()
#print 'CWebBrowser.moveEvent', event.pos().x(), event.pos().y(), event.oldPos().x(), event.oldPos().y(), '*', delta.x(), delta.y()
self.emit(QtCore.SIGNAL('windowMoved'), delta)
event.ignore()
def openSendReport(self):
from qtgui import CCP4ErrorReportViewer
widget = CCP4ErrorReportViewer.CSendJobError(self, projectId=self.getProject())
widget.show()
def openUpdate(self):
from qtgui import CCP4UpdateDialog
widget = CCP4UpdateDialog.CUpdateDialog(self)
widget.show()
def handleProjectMenuExport(self):
pass
def openManageImportFiles(self):
pass
class CFindFrame(QtGui.QFrame):
def __init__(self, parent):
QtGui.QFrame.__init__(self, parent)
import functools
find_layout = QtGui.QHBoxLayout()
margin = 2
find_layout.setContentsMargins(margin, margin, margin, margin)
find_layout.setSpacing(margin)
#widget = QtGui.QPushButton('Close', self)
#find_layout.addWidget(widget)
#self.connect(widget,QtCore.SIGNAL('clicked(bool)'), self.closeFind)
find_layout.addWidget(QtGui.QLabel('Find:'))
self.findTextWidget = QtGui.QLineEdit(self)
find_layout.addWidget(self.findTextWidget)
self.connect(self.findTextWidget,QtCore.SIGNAL('returnPressed()'), functools.partial(self.handleClicked, 'findNext'))
self.next = QtGui.QPushButton('Next', self)
find_layout.addWidget(self.next)
self.connect(self.next,QtCore.SIGNAL('clicked(bool)'), functools.partial(self.handleClicked, 'findNext'))
self.previous= QtGui.QPushButton('Previous', self)
find_layout.addWidget(self.previous)
self.connect(self.previous, QtCore.SIGNAL('clicked(bool)'), functools.partial(self.handleClicked, 'findPrevious'))
'''
self.all= QtGui.QPushButton('Highlight all',self)
find_layout.addWidget(self.all)
self.connect(self.all,QtCore.SIGNAL('clicked(bool)'),functools.partial(self.emit,QtCore.SIGNAL('highlightAll')))
'''
self.findCase = QtGui.QCheckBox('Match case', self)
find_layout.addWidget(self.findCase)
find_layout.addStretch(5)
self.wrap = QtGui.QCheckBox('Wrap', self)
find_layout.addWidget(self.wrap)
self.wrap.setChecked(1)
find_layout.addStretch(5)
self.setLayout(find_layout)
def handleClicked(self, mode, clickBool=False):
#print 'CFindFrame.handleClicked',mode,clickBool
self.emit(QtCore.SIGNAL(mode))
def text(self):
return str(self.findTextWidget.text())
def caseSensitive(self):
return self.findCase.isChecked()
def wrapAroundDocument(self):
return self.wrap.isChecked()