""" qtgui/main.py: CCP4MG Molecular Graphics Program Copyright (C) 2001-2008 University of York, CCLRC Copyright (C) 2009-2011 University of York Copyright (C) 2012 STFC 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,os,glob import re import time import traceback import functools try: # This only matters for site-packes installed version. # It is a stub which sets sys.path appropriately. import ccp4mg except: pass if sys.argv.count('-osmesa'): import mgOSMesa as opengl else: import opengl from PyQt4 import QtGui,QtCore,QtOpenGL import cprim SequenceViewer_initialized = 0 def LoadSequencesFromCommandLine(): from MGMainWindow import MGMainWindowCore import global_definitions SEQUENCE_SUFFIXES = [".pir",".fasta",".pfam",".gde",".rsf",".gcg",".cd",".amps",".gb",".msf",".clw",".afa",".seq"] def openSequence(args): global SequenceViewer_initialized if not SequenceViewer_initialized: initSequenceViewer() SequenceViewer_initialized = 1 from PyQt4 import QtCore print "Treat",args,"as sequence" global_definitions.MAINWINDOW().sequence_dialog.loadExternalAlignment(QtCore.QString(args)) def initSequenceViewer(): if not hasattr(global_definitions.MAINWINDOW(),"sequence_dialog"): import SequenceViewer SequenceViewer.initializePlugin() SequenceViewer.handleSequenceDialog() global_definitions.MAINWINDOW().sequence_dialog.ClearAlign() global_definitions.MAINWINDOW().sequence_dialog.sequence_displays = [] global_definitions.MAINWINDOW().sequence_dialog.resetModelandView() global_definitions.MAINWINDOW().sequence_dialog.updateUDDs() global_definitions.MAINWINDOW().sequence_dialog.applySelectionsFromDispobjs() global_definitions.MAINWINDOW().UnClose() def loadSequencesFromCommandLine(): for f in global_definitions.HISTORY().command_line_other_files: suffix = os.path.splitext(f)[1] if suffix.lower() in SEQUENCE_SUFFIXES: openSequence(f) loadSequencesFromCommandLine() if __name__ == "__main__" and sys.platform == "linux2": """ On 64 bit debian 5, File->Open somehow attempts to load /usr/lib/libxml2.so.2 which then resolves symbols incorrectly against ccp4mg/lib/libz.so.1. What *should* happen (and does everywhere else is that ccp4mg/lib/libxml2.so.2 should be loaded. Here, we force this to happen so that it is cached for later attempt. """ import platform platter = platform.platform() if 'debian-5' in platter and 'x86_64' in platter: import ctypes from ctypes.util import find_library cdum = ctypes.CDLL(find_library("xml2")) def random_splash_file(): file_list = glob.glob(os.path.join(os.environ["CCP4MG"],"splash",'*.png')) #print 'random_splash_file',file_list if not file_list: return os.path.join(os.environ["CCP4MG"],"splash.png") ii = int(time.time()%len(file_list)) return file_list[ii] class BevelledSplashScreen(QtGui.QSplashScreen): def __init__(self,pixmap): QtGui.QSplashScreen.__init__(self,pixmap) def drawContents(self,painter): QtGui.QSplashScreen.drawContents(self,painter) path = QtGui.QPainterPath() border_width = 4 path.moveTo(0,0) path.lineTo(border_width,border_width) path.lineTo(border_width,self.height()-(border_width)) path.lineTo(0,self.height()) path.lineTo(0,0) pen = QtGui.QPen(QtGui.QColor(0,0,0)) painter.setPen(pen) #brush = QtGui.QBrush(endColour) startColour = QtGui.QColor(255,255,255) endColour = QtGui.QColor(96,96,96) linearGrad = QtGui.QLinearGradient(QtCore.QPointF(10, 0),QtCore.QPointF(0, 0)) linearGrad.setColorAt(0,startColour) linearGrad.setColorAt(1,endColour) brush = QtGui.QBrush(linearGrad) painter.fillPath(path,brush) path = QtGui.QPainterPath() path.moveTo(self.width(),0) path.lineTo(self.width()-(border_width),border_width) path.lineTo(self.width()-(border_width),self.height()-(border_width)) path.lineTo(self.width(),self.height()) path.lineTo(self.width(),0) #brush = QtGui.QBrush(QtGui.QColor(128,128,128)) startColour = QtGui.QColor(255,255,255) endColour = QtGui.QColor(96,96,96) linearGrad = QtGui.QLinearGradient(QtCore.QPointF(self.width()-(border_width), 0),QtCore.QPointF(self.width()-1, 0)) linearGrad.setColorAt(0,startColour) linearGrad.setColorAt(1,endColour) brush = QtGui.QBrush(linearGrad) painter.fillPath(path,brush) path = QtGui.QPainterPath() path.moveTo(0,0) path.lineTo(border_width,border_width) path.lineTo(self.width()-(border_width+1),border_width) path.lineTo(self.width(),0) path.lineTo(0,0) #brush = QtGui.QBrush(QtGui.QColor(192,192,192)) startColour = QtGui.QColor(255,255,255) endColour = QtGui.QColor(160,160,160) linearGrad = QtGui.QLinearGradient(QtCore.QPointF(0,border_width),QtCore.QPointF(0,0)) linearGrad.setColorAt(0,startColour) linearGrad.setColorAt(1,endColour) brush = QtGui.QBrush(linearGrad) painter.fillPath(path,brush) path = QtGui.QPainterPath() path.moveTo(0,self.height()) path.lineTo(border_width,self.height()-(border_width)) path.lineTo(self.width()-(border_width),self.height()-(border_width)) path.lineTo(self.width(),self.height()) path.lineTo(0,self.height()) #brush = QtGui.QBrush(QtGui.QColor(64,64,64)) startColour = QtGui.QColor(255,255,255) endColour = QtGui.QColor(32,32,32) linearGrad = QtGui.QLinearGradient(QtCore.QPointF(0,self.height()-(border_width+1)),QtCore.QPointF(0,self.height()-1)) linearGrad.setColorAt(0,startColour) linearGrad.setColorAt(1,endColour) brush = QtGui.QBrush(linearGrad) painter.fillPath(path,brush) class MainLoop: def __del__(self): print "Finishing CCP4MG MainLoop" def __init__(self): pass """ import resources self.resources = resources.CResources() self.resources.load_resources() """ def initialize(self,app): from MGMainWindow import MGMainWindow, MGMainWindowSimple import mgapp import global_definitions,rebuild developer = 1 # Parse the command line HISTORY = global_definitions.HISTORY() rv = HISTORY.parse_program_command_line() #HISTORY.recoverAutoSave() # rv!="" implies error parsing command line or command belongs to plugin # No need to go through usual exit protocols cos nothing set up if type(rv) == str and rv!="" and not sys.argv.count('-quit'): QtGui.QMessageBox.critical(None, "Input command not recognised",rv, QtGui.QMessageBox.Ok ) #translator = QtCore.QTranslator() # This is interesting, if a little silly in the latin case ... #translator.load(":/pyqtmg_la") #translator.load(":/pyqtmg_en") #app.installTranslator(translator) splash_file=random_splash_file() if not sys.argv.count('-quit'): pixmap = QtGui.QPixmap(splash_file) pix2 = QtGui.QPixmap(pixmap) pix2.fill(QtCore.Qt.white) painter = QtGui.QPainter() painter.begin(pix2) painter.drawPixmap(0,0,pixmap) painter.end() splash = BevelledSplashScreen(pix2) import version version_string = splash.tr("CCP4MG version ") + QtCore.QString(version.ccp4mg_version) if sys.platform != "linux2": splash.showMessage(splash.tr("Starting ")+version_string,QtCore.Qt.AlignHCenter|QtCore.Qt.AlignBottom,QtCore.Qt.black) splash.show() splash.raise_() if sys.platform == "linux2": splash.showMessage(splash.tr("Starting ")+version_string,QtCore.Qt.AlignHCenter|QtCore.Qt.AlignBottom,QtCore.Qt.black) dockedDT = 1 super_compact = 0 try: params2 = HISTORY.restore_params('params2') if params2 and hasattr(params2,"has_key") and params2.has_key('advanced_options'): advOpt = params2['advanced_options'] if advOpt and hasattr(advOpt,"has_key") and advOpt.has_key('dockable_display_table'): dockedDT = advOpt['dockable_display_table'] if advOpt and hasattr(advOpt,"has_key") and advOpt.has_key('super_compact_display_table'): super_compact = advOpt['super_compact_display_table'] except: pass if sys.argv.count('-quit'): window = MGMainWindowSimple(application=app,stereoFormatAvailable=stereoFormatAvailable) MGApplication._dummyWindow = window else: try: gui_params = HISTORY.restore_params('gui_params') window = MGMainWindow(application=app,gui_params=gui_params,stereoFormatAvailable=stereoFormatAvailable,dockedDT=dockedDT,super_compact=super_compact) except: window = MGMainWindow(application=app,stereoFormatAvailable=stereoFormatAvailable) settings = QtCore.QSettings("CCP4","CCP4MG") if not sys.argv.count('-quit'): window.restoreGeometry(settings.value("mainwindow/geometry").toByteArray()) window.show() window.setStyleSheet("""QMainWindow::separator { width: 6px; border: none; } """) import resources self.resources = resources.CResources() self.resources.load_resources() if not sys.argv.count('-quit'): splash.finish(window) window.UnClose() splash.raise_() if sys.argv.count('-quit'): window.hide() if hasattr(window,"wMGDisplayTable"): window.wMGDisplayTable.hide() """ import QResources resources = QResources.QResources() """ restore_past_or_prev = False askRestore = True if window.newRestore: askRestore = False for arg in sys.argv: if re.match('-nore',arg): askRestore = False break if not sys.argv.count('-quit'): try: if askRestore and HISTORY.check_data_valid_last_program_status(): restoreAnswer = QtGui.QMessageBox.question(window,"Restore status?","A saved status file exists. Would you like to restore it?",QtGui.QMessageBox.Yes| QtGui.QMessageBox.No,QtGui.QMessageBox.Yes) if restoreAnswer == QtGui.QMessageBox.Yes: restore_past_or_prev = True except: exc_type, exc_value,exc_tb = sys.exc_info()[:3] sys.stderr.write(str(exc_type)+'\n') sys.stderr.write(str(exc_value)+'\n') traceback.print_tb(exc_tb) else: restore_past_or_prev = True sys.setrecursionlimit(5000) if restore_past_or_prev: utils.printOutput( "Restoring program status..",developer) try: status = HISTORY.restore_program_status(restore_past_or_prev=restore_past_or_prev) if not sys.argv.count('-quit'): global_definitions.DISPLAYTABLE().loadAllDataObj() if status: utils.printOutput( "...DONE status: "+str(status)) else: utils.printOutput( "...DONE") except: exc_type, exc_value,exc_tb = sys.exc_info()[:3] sys.stderr.write(str(exc_type)+'\n') sys.stderr.write(str(exc_value)+'\n') traceback.print_tb(exc_tb) if not sys.argv.count('-quit'): window.applyGLLighting() # load plugins after restoring status so plugins can be handed saved # status as they are initialised window.setUpAskPrevStatus() window.loadPlugins() # Apply the command line requests utils.printOutput( "Applying command line..") try: status = HISTORY.apply_program_command_line() except: exc_type, exc_value,exc_tb = sys.exc_info()[:3] sys.stderr.write(str(exc_type)+'\n') sys.stderr.write(str(exc_value)+'\n') traceback.print_tb(exc_tb) rs = HISTORY.run_command_line_script() LoadSequencesFromCommandLine() rebuild.UpdateDisplay() # I have no idea if this is platform independent #if len(sys.argv) > 1: # for i in range(1,len(sys.argv)): # event = QtGui.QFileOpenEvent(sys.argv[i]) # app.postEvent(app,event) if not sys.argv.count('-quit'): window.UnClose() if hasattr(window,"wMGDisplayTable"): try: window.wMGDisplayTable.UnClose() except: exc_type, exc_value,exc_tb = sys.exc_info()[:3] sys.stderr.write(str(exc_type)+'\n') sys.stderr.write(str(exc_value)+'\n') traceback.print_tb(exc_tb) window.applyStereoPrefs() if not sys.argv.count('-quit'): from global_definitions import PM,get_dispobj app.setProperty("flip_labels",False) params = PM("miscell_prefs").getparams() if params.has_key('flip_text'): app.setProperty("flip_labels",params['flip_text']) for dispobj in get_dispobj(): dispobj.set_redraw_text() import rebuild rebuild.UpdateDisplay() if type(rv) == list: for plug in window.plugins: if hasattr(plug,"parse_program_command_line"): rv = plug.parse_program_command_line(rv) rverr = "" if sys.argv.count('-quit') and not sys.argv.count('-serve'): while '-quit' in rv: rv.remove('-quit') while '-OSMesaO' in rv: i = rv.index('-OSMesaO') if i+10 and rv[i+1][0]!='-': rv.pop(i) rv.pop(i) while '-osmesa' in rv: i = rv.index('-osmesa') f = 'mgosmesa.png' if i+10 and rv[i+1][0]!='-': f = rv[i+1] rv.pop(i) rv.pop(i) if window and hasattr(window,"glWidget") and hasattr(window.glWidget,"osMesaBuffer"): print "Attempting to write file",f try: window.glWidget.setDoDraw(True) window.glWidget.updateGL() window.glWidget.write(f) window.glWidget.setDoDraw(False) print "Written",f except: exc_type, exc_value = sys.exc_info()[:2] print "Failed to write",f, exc_type, exc_value utils.deleteTemporaryFiles() if rv or status or rs: print "Quitting with error"; sys.stdout.flush() print rv, type(rv) print status, type(status) print rs, type(rs) sys.exit(1) else: print "Quitting successfully"; sys.stdout.flush() sys.exit() for s in rv: rverr = rverr + s + " " if rverr!="" and not sys.argv.count('-quit'): QtGui.QMessageBox.critical(None, "Input command not recognised","Input command not recognised: "+rverr, QtGui.QMessageBox.Ok ) print sys.argv if sys.argv.count('-serve'): def handleServerSignal(params): print "handleServerSignal",params if "command" in params and "render" in params["command"]: if "out" in params and len(params["out"])>0: args = {} outfile = params["out"][0] print "Render to",outfile for arg in ["stereo","stereo_angle","stereo_mode","size","smoothribbons","transparent","raytrace","darkinside"]: if arg in params and len(params[arg])>0: args[arg] = params[arg][0] print args argv = ['-R', outfile, '-RO',str(args)] print argv import PixieDialog PixieDialog.parse_program_command_line(argv) if "command" in params and "open" in params["command"]: if "file" in params and len(params["file"])>0: theFile = params["file"][0] window.openFile(theFile) print "serving"; sys.stdout.flush() import CCP4MGHTTPServer t = CCP4MGHTTPServer.CCP4MGHTTPServerThread() t.commandSignal.connect(handleServerSignal) t.start() def MyExit(): import utils if not sys.argv.count('-serve'): import global_definitions # Cleanup and save status global_definitions.DISPLAYTABLE().Exit() global_definitions.HISTORY().Exit() # ??? What about cleanup/save of plugin applications app.closeAllWindows() settings = QtCore.QSettings("CCP4","CCP4MG") settings.setValue("mainwindow/geometry",QtCore.QVariant(window.saveGeometry())) if hasattr(window,"wMGDisplayTable"): settings.setValue("displaytable/geometry",QtCore.QVariant(window.wMGDisplayTable.saveGeometry())) settings.sync() utils.deleteTemporaryFiles() import atexit atexit.register(MyExit) if not sys.argv.count('-quit') and hasattr(window,"wMGDisplayTable"): window.wMGDisplayTable.restoreGeometry(settings.value("displaytable/geometry").toByteArray()) window.wMGDisplayTable.show() settings.sync() class trace_print_statements_writer : def __init__(self, *writers) : self.writers = writers def flush(self) : for w in self.writers : w.flush() def write(self, text) : traceback.print_stack() for w in self.writers : w.write(text) if __name__ == "__main__": if os.environ.has_key("CCP4MG_DEBUG_TRACEPRINT"): sys.stdout = trace_print_statements_writer(sys.stdout) sys.argv = [ a for a in sys.argv if a != "-gdb" ] sys.argv = [ a for a in sys.argv if a != "-valgrind" ] if sys.platform == "win32": import mg2 mg2.setup_pythonpath() import crash_handler import datetime import tempfile if sys.platform == "win32": tdir = tempfile.gettempdir() dumpfile = os.path.join(tdir,"CCP4MG_"+str(datetime.date.today())+'_'+time.strftime("%H-%M-%S")+".mdmp") crash_handler.SetCrashHandler(dumpfile) import MGApplication import utils # Intercept a -help command line before setting everything up if sys.argv.count('-help') or sys.argv.count('-h'): helpfile = os.path.join(os.environ["CCP4MG"],'python','etc','help.txt') f=utils.openFile(helpfile,'r',1) if f: helptext=f.read() f.close() print helptext sys.exit() # Intercept a -version command line before setting everything up if sys.argv.count('-version'): from version import ccp4mg_version print ccp4mg_version sys.exit() tex_f = open(os.path.join(os.environ["CCP4MG"],"shaders","textures","atom_texture_coords_table")) tex_atoms = {} for l in tex_f.readlines(): tsx, tex,tsy,tey = l[2:].split() cprim.TexCoords().AddCoords(l[:2],float(tsx),float(tex),float(tsy),float(tey)) tex_f.close() # Do the optional redirection early in startup sequence. if sys.argv.count('-redirect')>0: while sys.argv.count('-redirect')>0: sys.argv.remove('-redirect') if sys.argv.count('-noredirect')>0: while sys.argv.count('-noredirect')>0: sys.argv.remove('-noredirect') else: utils.redirectOutput() if sys.argv.count('-noredirect')>0: while sys.argv.count('-noredirect')>0: sys.argv.remove('-noredirect') if not sys.argv.count('-quit'): #QtGui.QApplication.setGraphicsSystem("raster") app = MGApplication.MGApplication(sys.argv) else: if sys.platform != "win32": app = QtGui.QApplication(sys.argv,False) else: app = QtGui.QApplication(sys.argv,True) app.setAttribute(QtCore.Qt.AA_DontShowIconsInMenus,False) app.setProperty("flip_labels",False) if not sys.argv.count('-quit'): stereoFormat = QtOpenGL.QGLFormat(QtOpenGL.QGL.StereoBuffers) glWidgetTest = QtOpenGL.QGLWidget(stereoFormat) stereoFormatAvailable = glWidgetTest.format().stereo() glWidgetTest.close() glWidgetTest.deleteLater() else: stereoFormatAvailable = False app.addLibraryPath(os.path.join(os.environ["CCP4MG"],"QtPlugins")) if os.environ.has_key("CCP4"): app.addLibraryPath(os.path.join(os.environ["CCP4"],"QtPlugins")) app.addLibraryPath(os.path.join(os.environ["CCP4"],"lib","qt4","plugins")) def MyExit(): print "Exiting" mainloops = [] import atexit atexit.register(MyExit) m = MainLoop() import MainLoopContainer MainLoopContainer.MainLoopContainer.append(m) m.initialize(app) app.emit(QtCore.SIGNAL("ApplicationReady"), (app)) sys.exit(app.exec_())