Ejemplo n.º 1
0
    def __init__(self):
        super(ICECacheExplorerWindow, self).__init__()

        self.setStyleSheet(CONSTS.SS_BACKGROUND)

        self.setWindowTitle("ICE Explorer")
        self.setWindowIcon(QtGui.QIcon('./resources/icex.png'))

        self._create_statusbar()

        self.prefs = ICEPreferences(self)

        # setup the OGL window
        self.viewer = ICEViewer(self)
        self.viewer.cacheLoaded.connect(self._on_cache_loaded)
        self.viewer.beginCacheLoading.connect(self._on_begin_cache_loading)
        self.viewer.endCacheLoading.connect(self._on_end_cache_loading)
        self.setCentralWidget(self.viewer)

        # create object responsible for exporting attributes in the browser
        self.exporter = ICEExporter(self)
        self.exporter.cacheExporting.connect(self._on_cache_exporting)
        self.exporter.beginCacheExporting.connect(
            self._on_begin_cache_exporting)
        self.exporter.endCacheExporting.connect(self._on_end_cache_exporting)

        # create object responsible for loading attributes data in the browser
        self.data_loader = ICEDataLoader(self)
        self.data_loader.cacheDataLoaded.connect(self._on_cache_data_loaded)
        self.data_loader.beginCacheDataLoading.connect(
            self._on_begin_cache_data_loading)
        self.data_loader.endCacheDataLoading.connect(
            self._on_end_cache_data_loading)

        self._create_actions()
        self._create_menus()
        self._create_toolbars()
        self._create_dock_windows()

        self.current_job = None
        self._cache_files = []
Ejemplo n.º 2
0
    def __init__(self):
        super(ICECacheExplorerWindow, self).__init__()

        self.setStyleSheet(CONSTS.SS_BACKGROUND)

        self.setWindowTitle("ICE Explorer")
        self.setWindowIcon(QtGui.QIcon('./resources/icex.png'))

        self._create_statusbar()

        self.prefs = ICEPreferences(self)

        # setup the OGL window
        self.viewer = ICEViewer(self)
        self.viewer.cacheLoaded.connect(self._on_cache_loaded)
        self.viewer.beginCacheLoading.connect(self._on_begin_cache_loading)
        self.viewer.endCacheLoading.connect(self._on_end_cache_loading)        
        self.setCentralWidget(self.viewer)
        
        # create object responsible for exporting attributes in the browser
        self.exporter = ICEExporter( self ) 
        self.exporter.cacheExporting.connect(self._on_cache_exporting)
        self.exporter.beginCacheExporting.connect(self._on_begin_cache_exporting)
        self.exporter.endCacheExporting.connect(self._on_end_cache_exporting)
        
        # create object responsible for loading attributes data in the browser
        self.data_loader = ICEDataLoader(self)        
        self.data_loader.cacheDataLoaded.connect(self._on_cache_data_loaded)
        self.data_loader.beginCacheDataLoading.connect(self._on_begin_cache_data_loading)
        self.data_loader.endCacheDataLoading.connect(self._on_end_cache_data_loading)
        
        self._create_actions()
        self._create_menus()
        self._create_toolbars()
        self._create_dock_windows()
                
        self.current_job = None
        self._cache_files = []
Ejemplo n.º 3
0
class ICECacheExplorerWindow(QtGui.QMainWindow):
    """ This is the main window for ICE Explorer """
    
    # Supported I/O jobs
    LOAD = 0
    EXPORT = 1
    def __init__(self):
        super(ICECacheExplorerWindow, self).__init__()

        self.setStyleSheet(CONSTS.SS_BACKGROUND)

        self.setWindowTitle("ICE Explorer")
        self.setWindowIcon(QtGui.QIcon('./resources/icex.png'))

        self._create_statusbar()

        self.prefs = ICEPreferences(self)

        # setup the OGL window
        self.viewer = ICEViewer(self)
        self.viewer.cacheLoaded.connect(self._on_cache_loaded)
        self.viewer.beginCacheLoading.connect(self._on_begin_cache_loading)
        self.viewer.endCacheLoading.connect(self._on_end_cache_loading)        
        self.setCentralWidget(self.viewer)
        
        # create object responsible for exporting attributes in the browser
        self.exporter = ICEExporter( self ) 
        self.exporter.cacheExporting.connect(self._on_cache_exporting)
        self.exporter.beginCacheExporting.connect(self._on_begin_cache_exporting)
        self.exporter.endCacheExporting.connect(self._on_end_cache_exporting)
        
        # create object responsible for loading attributes data in the browser
        self.data_loader = ICEDataLoader(self)        
        self.data_loader.cacheDataLoaded.connect(self._on_cache_data_loaded)
        self.data_loader.beginCacheDataLoading.connect(self._on_begin_cache_data_loading)
        self.data_loader.endCacheDataLoading.connect(self._on_end_cache_data_loading)
        
        self._create_actions()
        self._create_menus()
        self._create_toolbars()
        self._create_dock_windows()
                
        self.current_job = None
        self._cache_files = []
                
    def _load_cache_folder(self):
        """ Load cache folder from a directory dialog """
        self.statusBar().clearMessage()
        
        fileDialog = QtGui.QFileDialog(self, caption="Select ICECache Folder To Load", directory=".")
        fileDialog.setFileMode(QtGui.QFileDialog.DirectoryOnly)
        fileDialog.setAcceptMode(QtGui.QFileDialog.AcceptOpen)
        fileDialog.setOptions(QtGui.QFileDialog.ShowDirsOnly)
        if not fileDialog.exec_():
            return
                
        self.current_job = self.LOAD
        self.viewer.load_files_from_folder(fileDialog.directory().absolutePath())                
        
    def _load_cache(self):
        """ Load cache file from a file dialog """
        self.statusBar().clearMessage()
        
        fileDialog = QtGui.QFileDialog(self, caption="Select ICECache File(s) To Load", directory=".", filter="ICECACHE (*.icecache *.sih5)")
        fileDialog.setFileMode(QtGui.QFileDialog.ExistingFiles)
        fileDialog.setAcceptMode(QtGui.QFileDialog.AcceptOpen)
        if not fileDialog.exec_():
            return
        
        self.viewer.load_files(fileDialog.selectedFiles())

    def _export_to_text(self):
        """ Select folder cache and export cache files to text """
        self.exporter.folder_dialog.open( CONSTS.TEXT_FMT )

    def _export_to_sih5(self):
        """ Select folder cache and export cache files to SIH5"""
        self.exporter.folder_dialog.open( CONSTS.SIH5_FMT )
    
    def _export_all_to_text(self):
        """ Export all cache files to text """
        self.statusBar().clearMessage()
        self.exporter.file_dialog.open( self._cache_files, CONSTS.TEXT_FMT )
        
    def _export_all_to_sih5(self):
        """ Export all cache files to SIH5 """
        self.statusBar().clearMessage()
        self.exporter.file_dialog.open( self._cache_files, CONSTS.SIH5_FMT )
                
    def preferences(self):
        self.prefs.exec_()

    def close(self):
        sys.exit()

    # Internals

    # slots for the export job
    def _on_begin_cache_exporting(self, num ):
        self.current_job = self.EXPORT
        self.cancel_current_job_act.setDisabled (False)
        self._start_progressbar(num,'Exporting...')

    def _on_cache_exporting(self, export_file):
        self._update_progressbar()

    def _on_end_cache_exporting(self):
        # and we are done
        self.current_job = None
        self.cancel_current_job_act.setDisabled(True)
        self._stop_progressbar()

    # slots for the cache data load job
    def _on_begin_cache_data_loading(self, cache_attrib, num ):
        self._start_progressbar( num, 'Loading data: %s' % (cache_attrib) )

    def _on_cache_data_loaded(self ):
        self._update_progressbar()

    def _on_end_cache_data_loading(self):
        self._stop_progressbar()

    # slots for the cache load job
    def _on_begin_cache_loading(self, count, start, end ):
        self.current_job = self.LOAD
        self.treeWidget.clear()
        self._cache_files = []
        self.cancel_current_job_act.setDisabled(False)
        self._start_progressbar( count, 'Loading Cache Files ...'  )
                
    def _on_end_cache_loading(self, count, start, end ):
        self.current_job = None
        self.cancel_current_job_act.setDisabled(True)
        self._stop_progressbar()

    def _on_cache_loaded(self, cacheindex, filename):
        """update the browser when a cache has finished loading"""
        if cacheindex == None:
            self.statusBar().showMessage( 'Error - invalid file: %s' % filename )
            return

        self._update_progressbar()

        self._cache_files.append( filename )
        
        # Creates browser top level items only, rest will be filled when items get expanded
        # cache item
        itemcache = QtGui.QTreeWidgetItem(self.treeWidget)
        itemcache.setText(0, 'Cache %d' % (cacheindex))
        indexVar = QtCore.QVariant(cacheindex)
        itemcache.setData(0, QtCore.Qt.UserRole, indexVar)
        self.treeWidget.addTopLevelItem(itemcache)
        
        # header item
        headeritem = QtGui.QTreeWidgetItem(itemcache)        
        headeritem.setText(0, 'Header')
        headeritem.setText(1, "ICECACHE")
                
    def _cancel_current_job(self):
        """ cancel the current executing I/O job """
        if self.current_job == self.LOAD:
            self.viewer.stop_loading()
        elif self.current_job == self.EXPORT:
            self.exporter.cancel()

    def _create_actions(self):
        """ All actions required by the GUI components """
        self.load_cache_folder_act = QtGui.QAction(QtGui.QIcon(r'./resources/load-cache-folder.png'), "&Load Cache Folder...", self, statusTip="Load Cache Folder", triggered=self._load_cache_folder)
        self.load_cache_act = QtGui.QAction(QtGui.QIcon(r'./resources/load-cache-file.png'), "Load Cache &File(s)...", self, statusTip="Load Cache File(s)", triggered=self._load_cache)
        self.export_all_caches_to_text_act = QtGui.QAction(QtGui.QIcon(r'./resources/export-cache.png'), "Export Caches to &Text", self, statusTip="Export Caches To Text", triggered=self._export_all_to_text)
        self.export_all_caches_to_sih5_act = QtGui.QAction(QtGui.QIcon(r'./resources/export-cache.png'), "Export Caches to &SIH5", self, statusTip="Export Caches To SIH5", triggered=self._export_all_to_sih5)
        self.export_caches_to_text_act = QtGui.QAction(QtGui.QIcon(r'./resources/export-cache-folder.png'), "Export Folder to &Text", self, statusTip="Export Folder To Text", triggered=self._export_to_text)
        self.export_caches_to_sih5_act = QtGui.QAction(QtGui.QIcon(r'./resources/export-cache-folder.png'), "Export Folder to &SIH5", self, statusTip="Export Folder To SIH5", triggered=self._export_to_sih5)
        self.export_selected_cache_to_text_act = QtGui.QAction(QtGui.QIcon(r'./resources/export-cache.png'), "Export Selected Cache To &Text", self, statusTip="Export To Text")
        self.export_selected_cache_to_sih5_act = QtGui.QAction(QtGui.QIcon(r'./resources/export-cache.png'), "Export Selected Cache To &SIH5", self, statusTip="Export To SIH5")
        self.cancel_current_job_act = QtGui.QAction(QtGui.QIcon(r'./resources/cancel_loading.png'), "Cancel", self, statusTip="Cancel", triggered=self._cancel_current_job)
        self.cancel_current_job_act.setDisabled(True)
        
        self.prefs_act = QtGui.QAction(QtGui.QIcon(r'./resources/preferences.png'), "&Preferences...", self, statusTip="ICE Explorer Preferences", triggered=self.preferences)
        self.quit_act = QtGui.QAction("&Quit", self, shortcut="Ctrl+Q", statusTip="Quit ICE Explorer", triggered=self.close)
        self.about_act = QtGui.QAction("&About", self, statusTip="Show About Dialog", triggered=self.about)

        self.show_pers_act = QtGui.QAction(QtGui.QIcon(r'./resources/perspective.png'), "&Perspective", self, statusTip="Show Perspective View", triggered=self.viewer.perspective_view)
        self.show_top_act = QtGui.QAction(QtGui.QIcon(r'./resources/top.png'), "&Top", self, statusTip="Show Top View", triggered=self.viewer.top_view)
        self.show_front_act = QtGui.QAction(QtGui.QIcon(r'./resources/front.png'), "&Front", self, statusTip="Show Front View", triggered=self.viewer.front_view)
        self.show_right_act = QtGui.QAction(QtGui.QIcon(r'./resources/right.png'), "&Right", self, statusTip="Show Right View", triggered=self.viewer.right_view)

        self.zoom_tool_act = QtGui.QAction(QtGui.QIcon(r'./resources/zoom.png'), "&Zoom", self, statusTip="Zoom Tool", triggered=self.viewer.zoom_tool)
        self.orbit_tool_act = QtGui.QAction(QtGui.QIcon(r'./resources/orbit.png'), "&Orbit", self, statusTip="Orbit Tool", triggered=self.viewer.orbit_tool)
        self.pan_tool_act = QtGui.QAction(QtGui.QIcon(r'./resources/pan.png'), "&Pan", self, statusTip="Pan Tool", triggered=self.viewer.pan_tool)

    def _create_menus(self): 
        self.menuBar().setStyleSheet(CONSTS.SS_MENUBAR)
        
        self.fileMenu = self.menuBar().addMenu("&File")        
        self.fileMenu.setStyleSheet(CONSTS.SS_MENU)
 
        self.fileMenu.addAction(self.load_cache_folder_act)
        self.fileMenu.addAction(self.load_cache_act)
        self.fileMenu.addSeparator()
        self.fileMenu.addAction(self.export_caches_to_text_act)
        self.fileMenu.addAction(self.export_caches_to_sih5_act)
        self.fileMenu.addSeparator()
        self.fileMenu.addAction(self.export_all_caches_to_text_act)
        self.fileMenu.addAction(self.export_all_caches_to_sih5_act)
        self.fileMenu.addAction(self.cancel_current_job_act)
        self.fileMenu.addSeparator()        
        self.fileMenu.addAction(self.cancel_current_job_act)
        self.fileMenu.addAction(self.quit_act)

        self.editMenu = self.menuBar().addMenu("&Edit")
        self.editMenu.setStyleSheet(CONSTS.SS_MENU)
        self.editMenu.addAction(self.prefs_act)
        
        self.viewMenu = self.menuBar().addMenu("&View")
        self.viewMenu.setStyleSheet(CONSTS.SS_MENU)

        self.helpMenu = self.menuBar().addMenu("&Help")
        self.helpMenu.addAction(self.about_act)
        self.helpMenu.setStyleSheet(CONSTS.SS_MENU)

    def _create_toolbars(self):
        self.fileToolBar = QtGui.QToolBar( "File" )
        self.fileToolBar.addAction(self.load_cache_folder_act)
        self.fileToolBar.addAction(self.load_cache_act)
        self.fileToolBar.addSeparator()
        self.fileToolBar.addAction(self.cancel_current_job_act)
        self.addToolBar( QtCore.Qt.LeftToolBarArea, self.fileToolBar )
        
        self.toolsToolBar = QtGui.QToolBar( "Tools" )        
        self.toolsToolBar.addAction(self.orbit_tool_act)
        self.toolsToolBar.addAction(self.pan_tool_act)
        self.toolsToolBar.addAction(self.zoom_tool_act)
        self.addToolBar( QtCore.Qt.LeftToolBarArea, self.toolsToolBar )

        self.viewToolBar = QtGui.QToolBar( "Views" )                
        self.viewToolBar.addAction(self.show_pers_act)
        self.viewToolBar.addAction(self.show_top_act)
        self.viewToolBar.addAction(self.show_front_act)
        self.viewToolBar.addAction(self.show_right_act)
        self.addToolBar( QtCore.Qt.LeftToolBarArea, self.viewToolBar )

    def _create_statusbar(self):
        """ The status bar contains a temporary message (left area ), a progress bar (left area) and a permanent msg on the right. """
        self.pbar = QtGui.QProgressBar(self.statusBar())
        self.pbar.setTextVisible(False)
        self.pbar.hide()        
        self.middle_msg = QtGui.QLabel(self.statusBar())
        self.right_msg = QtGui.QLabel(self.statusBar())

        self.statusBar().addWidget(self.pbar,2)
        self.statusBar().addWidget(self.middle_msg,1)
        self.statusBar().addPermanentWidget(self.right_msg)
        self.statusBar().showMessage("Ready")

    def _create_dock_windows(self):
        """ Creates and organizes all dockable windows"""
        
        # Cache file browser 
        dock = QtGui.QDockWidget("Browser", self)
        dock.setAllowedAreas(QtCore.Qt.LeftDockWidgetArea | QtCore.Qt.RightDockWidgetArea)
        self.treeWidget = QtGui.QTreeWidget(dock)
        self.treeWidget.itemExpanded.connect( self._handle_item_expanded )
        self.treeWidget.setObjectName('ICECacheInspectorWidget')
        self.treeWidget.setColumnCount(2)
        self.treeWidget.headerItem().setText(0, 'Item')
        self.treeWidget.headerItem().setText(1, 'Value')
        self.treeWidget.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.treeWidget.customContextMenuRequested.connect(self._handle_browser_contextmenu)
        self.treeWidget.setStyleSheet(CONSTS.SS_BACKGROUND)
        
        # ... browser context menus
        self._browser_contextmenu = QtGui.QMenu(self)
        self._browser_contextmenu.setStyleSheet(CONSTS.SS_MENU)
        self._browser_contextmenu.addAction(self.export_selected_cache_to_text_act)
        self._browser_contextmenu.addAction(self.export_selected_cache_to_sih5_act)
        self.attribute_contextmenu = QtGui.QMenu(self)
        self.attribute_contextmenu.setStyleSheet(CONSTS.SS_MENU)
        dock.setWidget(self.treeWidget)        
        self.addDockWidget(QtCore.Qt.RightDockWidgetArea, dock)
        self.viewMenu.addAction(dock.toggleViewAction())

        # Playback widget
        dock = QtGui.QDockWidget("Play Back", self)
        dock.setAllowedAreas(QtCore.Qt.BottomDockWidgetArea)        
        self.playback = PlaybackWidget(self.viewer, dock)                
        dock.setWidget(self.playback)            
        self.addDockWidget(QtCore.Qt.BottomDockWidgetArea, dock)
        self.viewMenu.addAction(dock.toggleViewAction())

    def _handle_item_expanded( self, item ):
        """ Fill items data when the node gets expanded """
        var = item.data(0, QtCore.Qt.UserRole)
        if var == None:
            # nothing to do
            return
        
        #Fill this item with cache attributes
        (cacheindex,flag) = var.toInt()
        h5cache = self.viewer.cache[ cacheindex ]
        
        if item.text(0) == 'Data':
            self.data_loader.load(h5cache,item)                  
            return

        #done with the user data
        item.setData(0, QtCore.Qt.UserRole, None)

        reader = H5Reader( h5cache )
        reader.load()
        
        # Cache
        #    > Header
        #         <header items>
        headeritem = item.child(0)
        headeritem.setText(0, 'Header')
        headeritem.setText(1, reader.header['name'])
        
        version = QtGui.QTreeWidgetItem(headeritem)
        type = QtGui.QTreeWidgetItem(headeritem)
        edge_count = QtGui.QTreeWidgetItem(headeritem)
        particle_count = QtGui.QTreeWidgetItem(headeritem)
        polygon_count = QtGui.QTreeWidgetItem(headeritem)
        sample_count = QtGui.QTreeWidgetItem(headeritem)
        blob_count = QtGui.QTreeWidgetItem(headeritem)
        attribute_count = QtGui.QTreeWidgetItem(headeritem)

        version.setText(0, 'Version')
        version.setText(1, str(reader.header['version']))
        type.setText(0, 'Type')
        type.setText(1, objtype_to_string(reader.header['type']))
        particle_count.setText(0, 'Particle Count')
        particle_count.setText(1, str(reader.header['particle_count']))
        edge_count.setText(0, 'Edge Count')
        edge_count.setText(1, str(reader.header['edge_count']))
        polygon_count.setText(0, 'Polygon Count')
        polygon_count.setText(1, str(reader.header['polygon_count']))
        sample_count.setText(0, 'Sample Count')
        sample_count.setText(1, str(reader.header['sample_count']))
        blob_count.setText(0, 'Blob Count')
        blob_count.setText(1, str(reader.header['blob_count']))
        attribute_count.setText(0, 'Attribute Count')
        attribute_count.setText(1, str(reader.header['attribute_count']))

        # attribute items
        # Cache
        #    > Header
        #         <header items>
        #    > Attribute <name>
        #         <attribute items>        

        for attrib in reader.attributes:
            attribitem = QtGui.QTreeWidgetItem(item)
            attribitem.setText(0, 'Attribute')
            attribitem.setText(1, attrib['name'] )

            # attribute description
            datatype = QtGui.QTreeWidgetItem(attribitem)
            structtype = QtGui.QTreeWidgetItem(attribitem)
            contexttype = QtGui.QTreeWidgetItem(attribitem)
            objid = QtGui.QTreeWidgetItem(attribitem)
            category = QtGui.QTreeWidgetItem(attribitem)
            ptlocator_size = QtGui.QTreeWidgetItem(attribitem)
            blobtype_count = QtGui.QTreeWidgetItem(attribitem)
            blobtype_names = QtGui.QTreeWidgetItem(attribitem)
            isconstant = QtGui.QTreeWidgetItem(attribitem)
            dataitem = QtGui.QTreeWidgetItem(attribitem)

            datatype.setText(0, 'Data Type')
            datatype.setText(1, datatype_to_string(attrib['datatype']))
            structtype.setText(0, 'Structure Type')
            structtype.setText(1, structtype_to_string(attrib['structtype']))
            contexttype.setText(0, 'Context Type')
            contexttype.setText(1, contexttype_to_string(attrib['contexttype']))
            objid.setText(0, 'Object ID')
            objid.setText(1, str(attrib['objid']))
            category.setText(0, 'Category')
            category.setText(1, categorytype_to_string(attrib['category']))
            ptlocator_size.setText(0, 'PointLocator Size')
            ptlocator_size.setText(1, str(attrib['ptlocator_size']))
            blobtype_count.setText(0, 'Blob Type Count')
            blobtype_count.setText(1, str(attrib['blobtype_count']))
            blobtype_names.setText(0, 'Blob Type Name')
            blobtype_names.setText(1, str(attrib['blobtype_names']))
            # will be filled when the data gets loaded by the user
            isconstant.setText(0, 'Constant Data')            
            isconstant.setText(1, '')
            
            # attribute data items, empty for now
            # Cache
            #    > Header 
            #         <header items>
            #    > Attribute <name>
            #         <attribute items>        
            #         > Data
            #              <values>
            dataitem.setText(0, 'Data')
            var = QtCore.QVariant(cacheindex)
            dataitem.setData(0, QtCore.Qt.UserRole, var )            

            # add dummy value so data item can get filled with values when it get expanded
            emptyvalue = QtGui.QTreeWidgetItem( dataitem )
            emptyvalue.setText( 0, '' )

    def _handle_browser_contextmenu(self, point):
        """ Context menus for  exporting individual cache files"""
        item = self.treeWidget.currentItem() 
        
        # show browser context menu on the widget
        if item.parent() != None:
            # context menu supported on the top level item only
            return
        
        action = self._browser_contextmenu.exec_(self.treeWidget.mapToGlobal(point))
        var = item.data(0, QtCore.Qt.UserRole)
        (cache_index,flag) = var.toInt()
        fmt=None
        if action == self.export_selected_cache_to_text_act:
            fmt = CONSTS.TEXT_FMT
        elif action == self.export_selected_cache_to_sih5_act:                
            fmt = CONSTS.SIH5_FMT
        else:
            return
        
        h5cache = self.viewer.cache[ cache_index ]
        self.exporter.export_files( [h5cache.filename], self.prefs.export_folder, fmt)                

    # Progress bar helpers
    def _start_progressbar(self,num,msg=''):        
        self.pbar.show()
        self.pbar.setRange(0, num)
        self.pbar.setValue(1)
        self.middle_msg.setText( msg )

    def _update_progressbar(self):        
        self.pbar.setValue(self.pbar.value() + 1)        

    def _stop_progressbar(self):        
        self.pbar.hide()
        self.pbar.reset()
        self.middle_msg.clear( )

    def about(self):
        msg = "<b>ICE Explorer</b> Copyright (C) 2010  M.A.Belzile <br>"\
            "A tool for viewing and browsing ICE cache data.<br>"\
            "Version %d.%d.%d %s %d<br><br>"\
            "This program comes with ABSOLUTELY NO WARRANTY; for details see the GNU General Public License."\
            "This is free software, and you are welcome to redistribute it under certain conditions; see the GNU General Public License for details."
        QtGui.QMessageBox.about(self, "About ICE Explorer", msg % (__version__[0], __version__[1], __version__[2], __version__[3], __version__[4]))
Ejemplo n.º 4
0
class ICECacheExplorerWindow(QtGui.QMainWindow):
    """ This is the main window for ICE Explorer """

    # Supported I/O jobs
    LOAD = 0
    EXPORT = 1

    def __init__(self):
        super(ICECacheExplorerWindow, self).__init__()

        self.setStyleSheet(CONSTS.SS_BACKGROUND)

        self.setWindowTitle("ICE Explorer")
        self.setWindowIcon(QtGui.QIcon('./resources/icex.png'))

        self._create_statusbar()

        self.prefs = ICEPreferences(self)

        # setup the OGL window
        self.viewer = ICEViewer(self)
        self.viewer.cacheLoaded.connect(self._on_cache_loaded)
        self.viewer.beginCacheLoading.connect(self._on_begin_cache_loading)
        self.viewer.endCacheLoading.connect(self._on_end_cache_loading)
        self.setCentralWidget(self.viewer)

        # create object responsible for exporting attributes in the browser
        self.exporter = ICEExporter(self)
        self.exporter.cacheExporting.connect(self._on_cache_exporting)
        self.exporter.beginCacheExporting.connect(
            self._on_begin_cache_exporting)
        self.exporter.endCacheExporting.connect(self._on_end_cache_exporting)

        # create object responsible for loading attributes data in the browser
        self.data_loader = ICEDataLoader(self)
        self.data_loader.cacheDataLoaded.connect(self._on_cache_data_loaded)
        self.data_loader.beginCacheDataLoading.connect(
            self._on_begin_cache_data_loading)
        self.data_loader.endCacheDataLoading.connect(
            self._on_end_cache_data_loading)

        self._create_actions()
        self._create_menus()
        self._create_toolbars()
        self._create_dock_windows()

        self.current_job = None
        self._cache_files = []

    def _load_cache_folder(self):
        """ Load cache folder from a directory dialog """
        self.statusBar().clearMessage()

        fileDialog = QtGui.QFileDialog(
            self, caption="Select ICECache Folder To Load", directory=".")
        fileDialog.setFileMode(QtGui.QFileDialog.DirectoryOnly)
        fileDialog.setAcceptMode(QtGui.QFileDialog.AcceptOpen)
        fileDialog.setOptions(QtGui.QFileDialog.ShowDirsOnly)
        if not fileDialog.exec_():
            return

        self.current_job = self.LOAD
        self.viewer.load_files_from_folder(
            fileDialog.directory().absolutePath())

    def _load_cache(self):
        """ Load cache file from a file dialog """
        self.statusBar().clearMessage()

        fileDialog = QtGui.QFileDialog(
            self,
            caption="Select ICECache File(s) To Load",
            directory=".",
            filter="ICECACHE (*.icecache *.sih5)")
        fileDialog.setFileMode(QtGui.QFileDialog.ExistingFiles)
        fileDialog.setAcceptMode(QtGui.QFileDialog.AcceptOpen)
        if not fileDialog.exec_():
            return

        self.viewer.load_files(fileDialog.selectedFiles())

    def _export_to_text(self):
        """ Select folder cache and export cache files to text """
        self.exporter.folder_dialog.open(CONSTS.TEXT_FMT)

    def _export_to_sih5(self):
        """ Select folder cache and export cache files to SIH5"""
        self.exporter.folder_dialog.open(CONSTS.SIH5_FMT)

    def _export_all_to_text(self):
        """ Export all cache files to text """
        self.statusBar().clearMessage()
        self.exporter.file_dialog.open(self._cache_files, CONSTS.TEXT_FMT)

    def _export_all_to_sih5(self):
        """ Export all cache files to SIH5 """
        self.statusBar().clearMessage()
        self.exporter.file_dialog.open(self._cache_files, CONSTS.SIH5_FMT)

    def preferences(self):
        self.prefs.exec_()

    def close(self):
        sys.exit()

    # Internals

    # slots for the export job
    def _on_begin_cache_exporting(self, num):
        self.current_job = self.EXPORT
        self.cancel_current_job_act.setDisabled(False)
        self._start_progressbar(num, 'Exporting...')

    def _on_cache_exporting(self, export_file):
        self._update_progressbar()

    def _on_end_cache_exporting(self):
        # and we are done
        self.current_job = None
        self.cancel_current_job_act.setDisabled(True)
        self._stop_progressbar()

    # slots for the cache data load job
    def _on_begin_cache_data_loading(self, cache_attrib, num):
        self._start_progressbar(num, 'Loading data: %s' % (cache_attrib))

    def _on_cache_data_loaded(self):
        self._update_progressbar()

    def _on_end_cache_data_loading(self):
        self._stop_progressbar()

    # slots for the cache load job
    def _on_begin_cache_loading(self, count, start, end):
        self.current_job = self.LOAD
        self.treeWidget.clear()
        self._cache_files = []
        self.cancel_current_job_act.setDisabled(False)
        self._start_progressbar(count, 'Loading Cache Files ...')

    def _on_end_cache_loading(self, count, start, end):
        self.current_job = None
        self.cancel_current_job_act.setDisabled(True)
        self._stop_progressbar()

    def _on_cache_loaded(self, cacheindex, filename):
        """update the browser when a cache has finished loading"""
        if cacheindex == None:
            self.statusBar().showMessage('Error - invalid file: %s' % filename)
            return

        self._update_progressbar()

        self._cache_files.append(filename)

        # Creates browser top level items only, rest will be filled when items get expanded
        # cache item
        itemcache = QtGui.QTreeWidgetItem(self.treeWidget)
        itemcache.setText(0, 'Cache %d' % (cacheindex))
        indexVar = QtCore.QVariant(cacheindex)
        itemcache.setData(0, QtCore.Qt.UserRole, indexVar)
        self.treeWidget.addTopLevelItem(itemcache)

        # header item
        headeritem = QtGui.QTreeWidgetItem(itemcache)
        headeritem.setText(0, 'Header')
        headeritem.setText(1, "ICECACHE")

    def _cancel_current_job(self):
        """ cancel the current executing I/O job """
        if self.current_job == self.LOAD:
            self.viewer.stop_loading()
        elif self.current_job == self.EXPORT:
            self.exporter.cancel()

    def _create_actions(self):
        """ All actions required by the GUI components """
        self.load_cache_folder_act = QtGui.QAction(
            QtGui.QIcon(r'./resources/load-cache-folder.png'),
            "&Load Cache Folder...",
            self,
            statusTip="Load Cache Folder",
            triggered=self._load_cache_folder)
        self.load_cache_act = QtGui.QAction(
            QtGui.QIcon(r'./resources/load-cache-file.png'),
            "Load Cache &File(s)...",
            self,
            statusTip="Load Cache File(s)",
            triggered=self._load_cache)
        self.export_all_caches_to_text_act = QtGui.QAction(
            QtGui.QIcon(r'./resources/export-cache.png'),
            "Export Caches to &Text",
            self,
            statusTip="Export Caches To Text",
            triggered=self._export_all_to_text)
        self.export_all_caches_to_sih5_act = QtGui.QAction(
            QtGui.QIcon(r'./resources/export-cache.png'),
            "Export Caches to &SIH5",
            self,
            statusTip="Export Caches To SIH5",
            triggered=self._export_all_to_sih5)
        self.export_caches_to_text_act = QtGui.QAction(
            QtGui.QIcon(r'./resources/export-cache-folder.png'),
            "Export Folder to &Text",
            self,
            statusTip="Export Folder To Text",
            triggered=self._export_to_text)
        self.export_caches_to_sih5_act = QtGui.QAction(
            QtGui.QIcon(r'./resources/export-cache-folder.png'),
            "Export Folder to &SIH5",
            self,
            statusTip="Export Folder To SIH5",
            triggered=self._export_to_sih5)
        self.export_selected_cache_to_text_act = QtGui.QAction(
            QtGui.QIcon(r'./resources/export-cache.png'),
            "Export Selected Cache To &Text",
            self,
            statusTip="Export To Text")
        self.export_selected_cache_to_sih5_act = QtGui.QAction(
            QtGui.QIcon(r'./resources/export-cache.png'),
            "Export Selected Cache To &SIH5",
            self,
            statusTip="Export To SIH5")
        self.cancel_current_job_act = QtGui.QAction(
            QtGui.QIcon(r'./resources/cancel_loading.png'),
            "Cancel",
            self,
            statusTip="Cancel",
            triggered=self._cancel_current_job)
        self.cancel_current_job_act.setDisabled(True)

        self.prefs_act = QtGui.QAction(
            QtGui.QIcon(r'./resources/preferences.png'),
            "&Preferences...",
            self,
            statusTip="ICE Explorer Preferences",
            triggered=self.preferences)
        self.quit_act = QtGui.QAction("&Quit",
                                      self,
                                      shortcut="Ctrl+Q",
                                      statusTip="Quit ICE Explorer",
                                      triggered=self.close)
        self.about_act = QtGui.QAction("&About",
                                       self,
                                       statusTip="Show About Dialog",
                                       triggered=self.about)

        self.show_pers_act = QtGui.QAction(
            QtGui.QIcon(r'./resources/perspective.png'),
            "&Perspective",
            self,
            statusTip="Show Perspective View",
            triggered=self.viewer.perspective_view)
        self.show_top_act = QtGui.QAction(QtGui.QIcon(r'./resources/top.png'),
                                          "&Top",
                                          self,
                                          statusTip="Show Top View",
                                          triggered=self.viewer.top_view)
        self.show_front_act = QtGui.QAction(
            QtGui.QIcon(r'./resources/front.png'),
            "&Front",
            self,
            statusTip="Show Front View",
            triggered=self.viewer.front_view)
        self.show_right_act = QtGui.QAction(
            QtGui.QIcon(r'./resources/right.png'),
            "&Right",
            self,
            statusTip="Show Right View",
            triggered=self.viewer.right_view)

        self.zoom_tool_act = QtGui.QAction(
            QtGui.QIcon(r'./resources/zoom.png'),
            "&Zoom",
            self,
            statusTip="Zoom Tool",
            triggered=self.viewer.zoom_tool)
        self.orbit_tool_act = QtGui.QAction(
            QtGui.QIcon(r'./resources/orbit.png'),
            "&Orbit",
            self,
            statusTip="Orbit Tool",
            triggered=self.viewer.orbit_tool)
        self.pan_tool_act = QtGui.QAction(QtGui.QIcon(r'./resources/pan.png'),
                                          "&Pan",
                                          self,
                                          statusTip="Pan Tool",
                                          triggered=self.viewer.pan_tool)

    def _create_menus(self):
        self.menuBar().setStyleSheet(CONSTS.SS_MENUBAR)

        self.fileMenu = self.menuBar().addMenu("&File")
        self.fileMenu.setStyleSheet(CONSTS.SS_MENU)

        self.fileMenu.addAction(self.load_cache_folder_act)
        self.fileMenu.addAction(self.load_cache_act)
        self.fileMenu.addSeparator()
        self.fileMenu.addAction(self.export_caches_to_text_act)
        self.fileMenu.addAction(self.export_caches_to_sih5_act)
        self.fileMenu.addSeparator()
        self.fileMenu.addAction(self.export_all_caches_to_text_act)
        self.fileMenu.addAction(self.export_all_caches_to_sih5_act)
        self.fileMenu.addAction(self.cancel_current_job_act)
        self.fileMenu.addSeparator()
        self.fileMenu.addAction(self.cancel_current_job_act)
        self.fileMenu.addAction(self.quit_act)

        self.editMenu = self.menuBar().addMenu("&Edit")
        self.editMenu.setStyleSheet(CONSTS.SS_MENU)
        self.editMenu.addAction(self.prefs_act)

        self.viewMenu = self.menuBar().addMenu("&View")
        self.viewMenu.setStyleSheet(CONSTS.SS_MENU)

        self.helpMenu = self.menuBar().addMenu("&Help")
        self.helpMenu.addAction(self.about_act)
        self.helpMenu.setStyleSheet(CONSTS.SS_MENU)

    def _create_toolbars(self):
        self.fileToolBar = QtGui.QToolBar("File")
        self.fileToolBar.addAction(self.load_cache_folder_act)
        self.fileToolBar.addAction(self.load_cache_act)
        self.fileToolBar.addSeparator()
        self.fileToolBar.addAction(self.cancel_current_job_act)
        self.addToolBar(QtCore.Qt.LeftToolBarArea, self.fileToolBar)

        self.toolsToolBar = QtGui.QToolBar("Tools")
        self.toolsToolBar.addAction(self.orbit_tool_act)
        self.toolsToolBar.addAction(self.pan_tool_act)
        self.toolsToolBar.addAction(self.zoom_tool_act)
        self.addToolBar(QtCore.Qt.LeftToolBarArea, self.toolsToolBar)

        self.viewToolBar = QtGui.QToolBar("Views")
        self.viewToolBar.addAction(self.show_pers_act)
        self.viewToolBar.addAction(self.show_top_act)
        self.viewToolBar.addAction(self.show_front_act)
        self.viewToolBar.addAction(self.show_right_act)
        self.addToolBar(QtCore.Qt.LeftToolBarArea, self.viewToolBar)

    def _create_statusbar(self):
        """ The status bar contains a temporary message (left area ), a progress bar (left area) and a permanent msg on the right. """
        self.pbar = QtGui.QProgressBar(self.statusBar())
        self.pbar.setTextVisible(False)
        self.pbar.hide()
        self.middle_msg = QtGui.QLabel(self.statusBar())
        self.right_msg = QtGui.QLabel(self.statusBar())

        self.statusBar().addWidget(self.pbar, 2)
        self.statusBar().addWidget(self.middle_msg, 1)
        self.statusBar().addPermanentWidget(self.right_msg)
        self.statusBar().showMessage("Ready")

    def _create_dock_windows(self):
        """ Creates and organizes all dockable windows"""

        # Cache file browser
        dock = QtGui.QDockWidget("Browser", self)
        dock.setAllowedAreas(QtCore.Qt.LeftDockWidgetArea
                             | QtCore.Qt.RightDockWidgetArea)
        self.treeWidget = QtGui.QTreeWidget(dock)
        self.treeWidget.itemExpanded.connect(self._handle_item_expanded)
        self.treeWidget.setObjectName('ICECacheInspectorWidget')
        self.treeWidget.setColumnCount(2)
        self.treeWidget.headerItem().setText(0, 'Item')
        self.treeWidget.headerItem().setText(1, 'Value')
        self.treeWidget.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.treeWidget.customContextMenuRequested.connect(
            self._handle_browser_contextmenu)
        self.treeWidget.setStyleSheet(CONSTS.SS_BACKGROUND)

        # ... browser context menus
        self._browser_contextmenu = QtGui.QMenu(self)
        self._browser_contextmenu.setStyleSheet(CONSTS.SS_MENU)
        self._browser_contextmenu.addAction(
            self.export_selected_cache_to_text_act)
        self._browser_contextmenu.addAction(
            self.export_selected_cache_to_sih5_act)
        self.attribute_contextmenu = QtGui.QMenu(self)
        self.attribute_contextmenu.setStyleSheet(CONSTS.SS_MENU)
        dock.setWidget(self.treeWidget)
        self.addDockWidget(QtCore.Qt.RightDockWidgetArea, dock)
        self.viewMenu.addAction(dock.toggleViewAction())

        # Playback widget
        dock = QtGui.QDockWidget("Play Back", self)
        dock.setAllowedAreas(QtCore.Qt.BottomDockWidgetArea)
        self.playback = PlaybackWidget(self.viewer, dock)
        dock.setWidget(self.playback)
        self.addDockWidget(QtCore.Qt.BottomDockWidgetArea, dock)
        self.viewMenu.addAction(dock.toggleViewAction())

    def _handle_item_expanded(self, item):
        """ Fill items data when the node gets expanded """
        var = item.data(0, QtCore.Qt.UserRole)
        if var == None:
            # nothing to do
            return

        #Fill this item with cache attributes
        (cacheindex, flag) = var.toInt()
        h5cache = self.viewer.cache[cacheindex]

        if item.text(0) == 'Data':
            self.data_loader.load(h5cache, item)
            return

        #done with the user data
        item.setData(0, QtCore.Qt.UserRole, None)

        reader = H5Reader(h5cache)
        reader.load()

        # Cache
        #    > Header
        #         <header items>
        headeritem = item.child(0)
        headeritem.setText(0, 'Header')
        headeritem.setText(1, reader.header['name'])

        version = QtGui.QTreeWidgetItem(headeritem)
        type = QtGui.QTreeWidgetItem(headeritem)
        edge_count = QtGui.QTreeWidgetItem(headeritem)
        particle_count = QtGui.QTreeWidgetItem(headeritem)
        polygon_count = QtGui.QTreeWidgetItem(headeritem)
        sample_count = QtGui.QTreeWidgetItem(headeritem)
        blob_count = QtGui.QTreeWidgetItem(headeritem)
        attribute_count = QtGui.QTreeWidgetItem(headeritem)

        version.setText(0, 'Version')
        version.setText(1, str(reader.header['version']))
        type.setText(0, 'Type')
        type.setText(1, objtype_to_string(reader.header['type']))
        particle_count.setText(0, 'Particle Count')
        particle_count.setText(1, str(reader.header['particle_count']))
        edge_count.setText(0, 'Edge Count')
        edge_count.setText(1, str(reader.header['edge_count']))
        polygon_count.setText(0, 'Polygon Count')
        polygon_count.setText(1, str(reader.header['polygon_count']))
        sample_count.setText(0, 'Sample Count')
        sample_count.setText(1, str(reader.header['sample_count']))
        blob_count.setText(0, 'Blob Count')
        blob_count.setText(1, str(reader.header['blob_count']))
        attribute_count.setText(0, 'Attribute Count')
        attribute_count.setText(1, str(reader.header['attribute_count']))

        # attribute items
        # Cache
        #    > Header
        #         <header items>
        #    > Attribute <name>
        #         <attribute items>

        for attrib in reader.attributes:
            attribitem = QtGui.QTreeWidgetItem(item)
            attribitem.setText(0, 'Attribute')
            attribitem.setText(1, attrib['name'])

            # attribute description
            datatype = QtGui.QTreeWidgetItem(attribitem)
            structtype = QtGui.QTreeWidgetItem(attribitem)
            contexttype = QtGui.QTreeWidgetItem(attribitem)
            objid = QtGui.QTreeWidgetItem(attribitem)
            category = QtGui.QTreeWidgetItem(attribitem)
            ptlocator_size = QtGui.QTreeWidgetItem(attribitem)
            blobtype_count = QtGui.QTreeWidgetItem(attribitem)
            blobtype_names = QtGui.QTreeWidgetItem(attribitem)
            isconstant = QtGui.QTreeWidgetItem(attribitem)
            dataitem = QtGui.QTreeWidgetItem(attribitem)

            datatype.setText(0, 'Data Type')
            datatype.setText(1, datatype_to_string(attrib['datatype']))
            structtype.setText(0, 'Structure Type')
            structtype.setText(1, structtype_to_string(attrib['structtype']))
            contexttype.setText(0, 'Context Type')
            contexttype.setText(1,
                                contexttype_to_string(attrib['contexttype']))
            objid.setText(0, 'Object ID')
            objid.setText(1, str(attrib['objid']))
            category.setText(0, 'Category')
            category.setText(1, categorytype_to_string(attrib['category']))
            ptlocator_size.setText(0, 'PointLocator Size')
            ptlocator_size.setText(1, str(attrib['ptlocator_size']))
            blobtype_count.setText(0, 'Blob Type Count')
            blobtype_count.setText(1, str(attrib['blobtype_count']))
            blobtype_names.setText(0, 'Blob Type Name')
            blobtype_names.setText(1, str(attrib['blobtype_names']))
            # will be filled when the data gets loaded by the user
            isconstant.setText(0, 'Constant Data')
            isconstant.setText(1, '')

            # attribute data items, empty for now
            # Cache
            #    > Header
            #         <header items>
            #    > Attribute <name>
            #         <attribute items>
            #         > Data
            #              <values>
            dataitem.setText(0, 'Data')
            var = QtCore.QVariant(cacheindex)
            dataitem.setData(0, QtCore.Qt.UserRole, var)

            # add dummy value so data item can get filled with values when it get expanded
            emptyvalue = QtGui.QTreeWidgetItem(dataitem)
            emptyvalue.setText(0, '')

    def _handle_browser_contextmenu(self, point):
        """ Context menus for  exporting individual cache files"""
        item = self.treeWidget.currentItem()

        # show browser context menu on the widget
        if item.parent() != None:
            # context menu supported on the top level item only
            return

        action = self._browser_contextmenu.exec_(
            self.treeWidget.mapToGlobal(point))
        var = item.data(0, QtCore.Qt.UserRole)
        (cache_index, flag) = var.toInt()
        fmt = None
        if action == self.export_selected_cache_to_text_act:
            fmt = CONSTS.TEXT_FMT
        elif action == self.export_selected_cache_to_sih5_act:
            fmt = CONSTS.SIH5_FMT
        else:
            return

        h5cache = self.viewer.cache[cache_index]
        self.exporter.export_files([h5cache.filename],
                                   self.prefs.export_folder, fmt)

    # Progress bar helpers
    def _start_progressbar(self, num, msg=''):
        self.pbar.show()
        self.pbar.setRange(0, num)
        self.pbar.setValue(1)
        self.middle_msg.setText(msg)

    def _update_progressbar(self):
        self.pbar.setValue(self.pbar.value() + 1)

    def _stop_progressbar(self):
        self.pbar.hide()
        self.pbar.reset()
        self.middle_msg.clear()

    def about(self):
        msg = "<b>ICE Explorer</b> Copyright (C) 2010  M.A.Belzile <br>"\
            "A tool for viewing and browsing ICE cache data.<br>"\
            "Version %d.%d.%d %s %d<br><br>"\
            "This program comes with ABSOLUTELY NO WARRANTY; for details see the GNU General Public License."\
            "This is free software, and you are welcome to redistribute it under certain conditions; see the GNU General Public License for details."
        QtGui.QMessageBox.about(
            self, "About ICE Explorer",
            msg % (__version__[0], __version__[1], __version__[2],
                   __version__[3], __version__[4]))