# -*- coding: utf-8 -*-
# This software and supporting documentation are distributed by
# Institut Federatif de Recherche 49
# CEA/NeuroSpin, Batiment 145,
# 91191 Gif-sur-Yvette cedex
# France
#
# This software is governed by the CeCILL license version 2 under
# French law and abiding by the rules of distribution of free software.
# You can use, modify and/or redistribute the software under the
# terms of the CeCILL license version 2 as circulated by CEA, CNRS
# and INRIA at the following URL "http://www.cecill.info".
#
# As a counterpart to the access to the source code and rights to copy,
# modify and redistribute granted by the license, users are provided only
# with a limited warranty and the software's author, the holder of the
# economic rights, and the successive licensors have only limited
# liability.
#
# In this respect, the user's attention is drawn to the risks associated
# with loading, using, modifying and/or developing or reproducing the
# software by the user in light of its specific status of free software,
# that may mean that it is complicated to manipulate, and that also
# therefore means that it is reserved for developers and experienced
# professionals having in-depth computer knowledge. Users are therefore
# encouraged to load and test the software's suitability as regards their
# requirements in conditions enabling the security of their systems and/or
# data to be ensured and, more generally, to use and operate it in the
# same conditions as regards security.
#
# The fact that you are presently reading this means that you have had
# knowledge of the CeCILL license version 2 and that you accept its terms.
from brainvisa.processing.qtgui.backwardCompatibleQt \
import QLineEdit, SIGNAL, QPushButton, QToolButton, \
Qt, QIcon, QWidget, QFileDialog, QVBoxLayout, \
QListWidget, QHBoxLayout, QSpacerItem, QSizePolicy, QSize, QMenu, \
QPalette, QColor
from soma.wip.application.api import findIconFile
from soma.qtgui.api import largeIconSize
from brainvisa.data.qtgui.diskItemBrowser import DiskItemBrowser
from brainvisa.data.qtgui.neuroDataGUI import DataEditor, StringListEditor, buttonMargin, buttonIconSize
import brainvisa.processes
from brainvisa.processing.qt4gui import neuroProcessesGUI
from brainvisa.data.neuroDiskItems import DiskItem, Directory
from brainvisa.data.qt4gui import history as historygui
from brainvisa.configuration import neuroConfig
from brainvisa.processing.neuroException import showException, HTMLMessage
from PyQt4 import QtCore
import sys, os
#----------------------------------------------------------------------------
class RightClickablePushButton( QPushButton ):
def mousePressEvent( self, e ):
if e.button() == Qt.RightButton:
self.emit( SIGNAL( 'rightPressed' ), self.mapToGlobal( e.pos() ) )
else:
QPushButton.mousePressEvent( self, e )
#----------------------------------------------------------------------------
class DiskItemEditor( QWidget, DataEditor ):
def __init__( self, parameter, parent, name, write = False, context = None ):
if getattr( DiskItemEditor, 'pixShow', None ) is None:
setattr( DiskItemEditor, 'pixShow', QIcon( findIconFile( 'eye.png' )) )
setattr( DiskItemEditor, 'pixEdit', QIcon( findIconFile( 'pencil.png' )) )
setattr( DiskItemEditor, 'pixDatabaseRead', QIcon( findIconFile( 'database_read.png' )) )
setattr( DiskItemEditor, 'pixDatabaseWrite', QIcon( findIconFile( 'database_write.png' )) )
setattr( DiskItemEditor, 'pixBrowseRead', QIcon( findIconFile( 'browse_read.png' )) )
setattr( DiskItemEditor, 'pixBrowseWrite', QIcon( findIconFile( 'browse_write.png' )) )
setattr( DiskItemEditor, 'pixHistory', QIcon( findIconFile( 'history.png' )) )
QWidget.__init__( self, parent )
if name:
self.setObjectName(name)
hLayout=QHBoxLayout()
self.setLayout(hLayout)
if sys.platform == 'darwin' and QtCore.qVersion() == '4.6.2':
# is this layout problem a bug in qt/Mac 4.6.2 ?
hLayout.setSpacing( 14 )
else:
hLayout.setSpacing( 2 )
hLayout.setContentsMargins( 0, 0, 0, 0 )
self._write = write
self.parameter = parameter
self.led = QLineEdit( )
hLayout.addWidget(self.led)
self.connect( self.led, SIGNAL( 'textChanged( const QString & )' ), self.textChanged )
self.connect( self.led, SIGNAL( 'returnPressed()' ), self.checkValue )
self.setFocusProxy( self.led )
self.diskItem = None
self.forceDefault = False
self._context = context
self.btnShow = RightClickablePushButton( )
hLayout.addWidget(self.btnShow)
self.btnShow.setCheckable(True)
self.btnShow.setIcon( self.pixShow )
self.btnShow.setIconSize(buttonIconSize)
self.btnShow.setFixedSize( buttonIconSize + buttonMargin )
self.btnShow.setFocusPolicy( Qt.NoFocus )
self.btnShow.setEnabled( False )
if not brainvisa.processes.getViewer( (self.parameter.type, self.parameter.formats[0] ), 1, checkUpdate=False ):
self.btnShow.hide()
self._view = None
self.connect( self.btnShow, SIGNAL( 'clicked()' ), self.showPressed )
self.connect( self.btnShow, SIGNAL( 'rightPressed' ), self.openViewerPressed )
self._edit = None
self.btnEdit = RightClickablePushButton( )
hLayout.addWidget(self.btnEdit)
self.btnEdit.setCheckable(True)
self.btnEdit.setIcon( self.pixEdit )
self.btnEdit.setIconSize(buttonIconSize)
self.btnEdit.setFixedSize( buttonIconSize + buttonMargin )
self.btnEdit.setFocusPolicy( Qt.NoFocus )
self.btnEdit.setEnabled( 0 )
if not brainvisa.processes.getDataEditor( (self.parameter.type, self.parameter.formats ), checkUpdate=False ):
self.btnEdit.hide()
self.connect( self.btnEdit, SIGNAL( 'clicked()' ), self.editPressed )
self.connect( self.btnEdit, SIGNAL( 'rightPressed' ),
self.openEditorPressed )
self.btnDatabase = QPushButton( )
hLayout.addWidget(self.btnDatabase)
if write:
self.btnDatabase.setIcon( self.pixDatabaseWrite )
self.btnDatabase.setIconSize(buttonIconSize)
self.btnDatabase.setToolTip(_t_("Browse the database (save mode)"))
else:
self.btnDatabase.setIcon( self.pixDatabaseRead )
self.btnDatabase.setIconSize(buttonIconSize)
self.btnDatabase.setToolTip(_t_("Browse the database (load mode)"))
self.btnDatabase.setFixedSize( buttonIconSize + buttonMargin )
self.btnDatabase.setFocusPolicy( Qt.NoFocus )
self.customFileDialog = None
if hasattr( parameter, 'fileDialog' ):
self.customFileDialog = parameter.fileDialog
if hasattr( parameter, 'databaseUserLevel' ):
x = parameter.databaseUserLevel
if x > neuroConfig.userLevel:
self.btnDatabase.hide()
self.connect( self.btnDatabase, SIGNAL( 'clicked()' ), self.databasePressed )
self.databaseDialog = None
self.btnBrowse = QPushButton( )
hLayout.addWidget(self.btnBrowse)
if write:
self.btnBrowse.setIcon( self.pixBrowseWrite )
self.btnBrowse.setIconSize(buttonIconSize)
self.btnBrowse.setToolTip(_t_("Browse the filesystem (save mode)"))
else:
self.btnBrowse.setIcon( self.pixBrowseRead )
self.btnBrowse.setIconSize(buttonIconSize)
self.btnBrowse.setToolTip(_t_("Browse the filesystem (load mode)"))
self.btnBrowse.setFixedSize( buttonIconSize + buttonMargin )
self.btnBrowse.setFocusPolicy( Qt.NoFocus )
if hasattr( parameter, 'browseUserLevel' ):
x = parameter.browseUserLevel
if x > neuroConfig.userLevel:
self.btnBrowse.hide()
self.connect( self.btnBrowse, SIGNAL( 'clicked()' ), self.browsePressed )
self.browseDialog = None
self._textChanged = False
def __del__( self ):
self._ = None
def set_read_only(self, read_only):
self.btnDatabase.setEnabled(not read_only)
self.btnBrowse.setEnabled(not read_only)
self.btnEdit.setEnabled(not read_only)
self.led.setReadOnly(read_only)
self.led.setFrame(not read_only)
def setContext( self, newContext ):
oldContext = ( self.btnShow.isChecked(), self._view,
self.btnEdit.isChecked(), self._edit )
if newContext is None:
self.btnShow.setChecked( False )
self.btnEdit.setChecked( False )
self._view = None
self._edit = None
else:
if len( newContext ) >=4:
o, v, z, e = newContext
else:
o, v = newContext
z = e = 0
self.btnShow.setChecked( o )
self._view = v
self.btnEdit.setChecked( z )
self._edit = e
return oldContext
def getValue( self ):
return self.diskItem
def setValue( self, value, default = 0 ):
self.forceDefault = default
if (self.diskItem != value):
self.diskItem = self.parameter.findValue( value )
if self.diskItem is None:
if value is None: self.led.setText( '' )
if self.btnShow: self.btnShow.setEnabled( 0 )
if self.btnEdit: self.btnEdit.setEnabled( 0 )
self.emit( SIGNAL('newValidValue'), unicode(self.objectName()), self.diskItem )
else:
self.led.setText( self.diskItem.fullPath() )
self.checkReadable()
self.emit( SIGNAL('newValidValue'), unicode(self.objectName()), self.diskItem )
self._textChanged = 0
self.forceDefault = 0
self.valuePropertiesChanged( default )
def valuePropertiesChanged( self, isDefault ):
pal = QPalette()
if not isDefault:
pal.setColor( QPalette.Text, QColor( 0, 0, 255 ) )
if self.diskItem is not None and self.diskItem.isLockData():
pal.setColor( QPalette.Base, QColor( 255, 230, 230 ) )
self.led.setPalette( pal )
def lockChanged( self, locked ):
pal = self.led.palette()
if self.diskItem is not None and self.diskItem.isLockData():
pal.setColor( QPalette.Base, QColor( 255, 230, 230 ) )
else:
pal2 = QPalette()
pal.setColor( QPalette.Base, pal2.color( QPalette.Base ) )
self.led.setPalette( pal )
def checkReadable( self ):
if self.btnShow:
enabled = 0
if self.diskItem:
v = brainvisa.processes.getViewer( self.diskItem, 1, checkUpdate=False )
if v:
self.btnShow.show()
else:
self.btnShow.hide()
if v:
enabled = self.diskItem.isReadable()
self.btnShow.setEnabled( enabled )
if self.btnEdit:
enabled = 0
v = brainvisa.processes.getDataEditor( (self.parameter.type, self.parameter.formats), checkUpdate=False )
if v:
self.btnEdit.show()
else:
self.btnEdit.hide()
if self.diskItem:
if v:
enabled = self.diskItem.isWriteable()
self.btnEdit.setEnabled( enabled )
def textChanged( self ):
self._textChanged = 1
if not self.forceDefault:
self.emit( SIGNAL('noDefault'), unicode(self.objectName()) )
def checkValue( self ):
if self._textChanged:
self.setValue( unicode( self.led.text() ) )
def showPressed( self ):
if self.btnShow.isChecked():
self.btnShow.setEnabled( 0 )
v = self.getValue()
viewerExists = False
try :
viewer = brainvisa.processes.getViewer( v, 1 )()
viewerExists = True
brainvisa.processes.defaultContext().runInteractiveProcess( self._viewerExited, viewer, v )
except Exception, error :
self.btnShow.setChecked( False )
if viewerExists:
self.btnShow.setEnabled( True )
raise RuntimeError( HTMLMessage( _t_( 'Viewer aborted for type =%s and format=%s (try using it interactively by right-clicking on the eye icon)' ) % (unicode( v.type ), unicode(v.format))) )
raise RuntimeError( HTMLMessage( _t_( 'No viewer could be found for type =%s and format=%s' ) % (unicode( v.type ), unicode(v.format))) )
else:
self._view = None
def _viewerExited( self, result ):
if isinstance( result, Exception ):
showException( parent=self )
else:
self._view = result
neuroProcessesGUI.mainThreadActions().push( self.btnShow.setEnabled, 1 )
if result is None:
neuroProcessesGUI.mainThreadActions().push( self.btnShow.setChecked, False )
def close_viewer(self):
if self._view is not None:
self._view = None
neuroProcessesGUI.mainThreadActions().push( self.btnShow.setChecked, False )
neuroProcessesGUI.mainThreadActions().push( self.btnShow.setEnabled, 1 )
def openViewerPressed( self, pos ):
v = self.getValue()
if v.get( 'lastHistoricalEvent' ):
popup = QMenu( self )
op = popup.addAction( DiskItemEditor.pixShow, 'open viewer' )
sh = popup.addAction( DiskItemEditor.pixHistory, 'show history' )
ac = popup.exec_( pos )
if ac is not None:
if ac is sh:
self.openHistory()
else:
self.openViewer()
else:
self.openViewer()
def openViewer( self ):
v = self.getValue()
viewer = brainvisa.processes.getViewer( v, 1 )()
neuroProcessesGUI.showProcess( viewer, v )
def openHistory( self ):
v = self.getValue()
bvproc_uuid = v.get("lastHistoricalEvent", None)
if bvproc_uuid is not None:
history_window = historygui.DataHistoryWindow( v, bvproc_uuid,
parent=self)
history_window.setAttribute( Qt.WA_DeleteOnClose )
history_window.show()
def editPressed( self ):
if self.btnEdit.isChecked():
self.btnEdit.setEnabled( 0 )
v = self.getValue()
editor = brainvisa.processes.getDataEditor( v )()
brainvisa.processes.defaultContext().runInteractiveProcess( self._editorExited, editor, v )
else:
self._edit = None
def _editorExited( self, result ):
if isinstance( result, Exception ):
showException( parent=self )
else:
self._edit = result
neuroProcessesGUI.mainThreadActions().push( self.btnEdit.setEnabled, True )
neuroProcessesGUI.mainThreadActions().push( self.btnEdit.setChecked, False )
def openEditorPressed( self ):
v = self.getValue()
editor = brainvisa.processes.getDataEditor( v )()
neuroProcessesGUI.showProcess( editor, v )
def databasePressed( self ):
if self.databaseDialog is None or self.parameter._modified:
self.parameter._modified = 0
if self.diskItem: # this parameter has already a value, use it to initialize the browser
selection = self.diskItem.hierarchyAttributes()
if self.diskItem.type is None :
selection[ '_type' ] = None
else :
selection[ '_type' ] = self.diskItem.type.name
if self.diskItem.format is None :
selection[ '_format' ] = None
else :
selection[ '_format' ] = self.diskItem.format.name
self.databaseDialog = DiskItemBrowser( self.parameter.database, selection=selection, required=self.parameter.requiredAttributes, parent=self, write = self._write,
enableConversion=self.parameter.enableConversion, exactType=self.parameter.exactType )
else: # if there is no value, we could have some selected attributes from a linked value, use it to initialize the browser
self.databaseDialog = DiskItemBrowser( self.parameter.database, selection=self.parameter._selectedAttributes, required=self.parameter.requiredAttributes, parent=self, write = self._write, enableConversion=self.parameter.enableConversion, exactType=self.parameter.exactType )
self.databaseDialog.setWindowTitle( _t_( self.parameter.type.name ) )
self.connect( self.databaseDialog, SIGNAL( 'accepted()' ), self.databaseAccepted )
else:
if self.diskItem:
self.databaseDialog.resetSelectedAttributes( self.diskItem )
#self.databaseDialog.rescan(selectedType=self.diskItem.type, selectedFormat=self.diskItem.format, selectedAttributes=self.diskItem.hierarchyAttributes())
else:
self.databaseDialog.resetSelectedAttributes( self.parameter._selectedAttributes )
#self.databaseDialog.rescan( selectedAttributes=self._selectedAttributes)
self.databaseDialog.show()
def databaseAccepted( self ):
values=self.databaseDialog.getValues()
if values:
self.setValue( values[0] )
def browsePressed( self ):
if self.browseDialog is None or self.parameter._modified:
self.parameter._modified = False
if self.customFileDialog:
self.browseDialog = self.customFileDialog( self )
else:
self.browseDialog = QFileDialog( self )
if self._write:
mode = QFileDialog.AnyFile
else:
mode = QFileDialog.ExistingFile
filters = []
allPatterns = {}
dirOnly = True
formats = set( self.parameter.formats )
if self.parameter.enableConversion:
for t in [ self.parameter.type ] + self.parameter.type.parents():
for f in self.parameter.formats:
conv = brainvisa.processes.getConvertersTo( ( t, f ) )
for t2, f2 in conv.iterkeys():
formats.add( f2 )
for f in formats:
if f.fileOrDirectory() is not Directory:
dirOnly = False
flt = f.getPatterns().unmatch( {}, { 'filename_variable': '*' } )[ 0 ]
allPatterns[ flt ] = 1
filters.append( _t_( f.name ) + ' (' + flt + ')' )
filters.insert( 0, _t_( 'Recognized formats' ) + ' (' \
+ ' '.join( allPatterns.keys() ) + ')' )
filters.append( _t_( 'All files' ) + ' (*)' )
if dirOnly:
mode = QFileDialog.Directory
self.browseDialog.setFileMode( mode )
self.browseDialog.setFilters( filters )
if self.customFileDialog and self.customFileDialog.customFilter != "":
self.browseDialog.selectFilter( self.customFileDialog.customFilter )
self.connect( self.browseDialog, SIGNAL( 'accepted()' ), self.browseAccepted )
# set current directory
parent = self._context
if hasattr( parent, '_currentDirectory' ) and parent._currentDirectory:
self.browseDialog.setDirectory( parent._currentDirectory )
else:
self.browseDialog.setDirectory( os.getcwd() )
self.browseDialog.show()
def browseAccepted( self ):
value = self.browseDialog.selectedFiles()
if (len(value) > 0):
value=unicode(value[0])
else:
value=None
parent = self._context
if hasattr( parent, '_currentDirectory' ):
parent._currentDirectory = unicode( self.browseDialog.directory().path() )
self.setValue( value )
def releaseCallbacks( self ):
self._view = None
self._edit = None
#----------------------------------------------------------------------------
class DiskItemListEditor( QWidget, DataEditor ):
class DiskItemListSelect( QWidget ): # Ex QSemiModal
def __init__( self, dilEditor, name, write, context = None,
databaseUserLevel=0, browseUserLevel=0 ):
self._context = context
if getattr( DiskItemListEditor.DiskItemListSelect, 'pixUp', None ) is None:
setattr( DiskItemListEditor.DiskItemListSelect, 'pixUp',
QIcon( findIconFile( 'up.png' )) )
setattr( DiskItemListEditor.DiskItemListSelect, 'pixDown',
QIcon( findIconFile( 'down.png' )) )
setattr( DiskItemListEditor.DiskItemListSelect, 'pixFindRead',
QIcon( findIconFile( 'database_read.png' )) )
setattr( DiskItemListEditor.DiskItemListSelect, 'pixFindWrite',
QIcon( findIconFile( 'database_write.png' )) )
setattr( DiskItemListEditor.DiskItemListSelect, 'pixBrowseRead',
QIcon( findIconFile( 'browse_read.png' )) )
setattr( DiskItemListEditor.DiskItemListSelect, 'pixBrowseWrite',
QIcon( findIconFile( 'browse_write.png' )) )
QWidget.__init__( self, dilEditor.topLevelWidget(), Qt.Dialog | Qt.WindowStaysOnTopHint )
if name:
self.setObjectName(name)
self.setAttribute(Qt.WA_DeleteOnClose, True)
self.setWindowModality(Qt.WindowModal)
layout = QVBoxLayout( )
layout.setContentsMargins( 10, 10, 10, 10 )
layout.setSpacing( 5 )
self.setLayout(layout)
self.dilEditor = dilEditor
self.parameter = dilEditor.parameter
self.values = []
self.browseDialog = None
self.findDialog = None
self.lbxValues = QListWidget( )
self.connect( self.lbxValues, SIGNAL('currentRowChanged( int )'), self._currentChanged )
layout.addWidget( self.lbxValues )
hb = QHBoxLayout()
hb.setSpacing( 6 )
self.btnAdd = QPushButton( _t_( 'Add' ) )
self.connect( self.btnAdd, SIGNAL( 'clicked()' ), self._add )
hb.addWidget( self.btnAdd )
self.btnRemove = QPushButton( _t_( 'Remove' ) )
self.btnRemove.setEnabled( 0 )
self.connect( self.btnRemove, SIGNAL( 'clicked()' ), self._remove )
hb.addWidget( self.btnRemove )
self.btnUp = QPushButton( )
self.btnUp.setIcon( self.pixUp )
self.btnUp.setIconSize(buttonIconSize)
self.btnUp.setEnabled( 0 )
self.connect( self.btnUp, SIGNAL( 'clicked()' ), self._up )
hb.addWidget( self.btnUp )
self.btnDown = QPushButton( )
self.btnDown.setIcon( self.pixDown )
self.btnDown.setEnabled( 0 )
self.connect( self.btnDown, SIGNAL( 'clicked()' ), self._down )
hb.addWidget( self.btnDown )
spacer = QSpacerItem( 10, 10, QSizePolicy.Expanding, QSizePolicy.Minimum )
hb.addItem( spacer )
layout.addLayout( hb )
hb = QHBoxLayout()
hb.setSpacing( 6 )
self.sle = StringListEditor( None, unicode(self.objectName()) )
hb.addWidget( self.sle )
btn = QPushButton( )
if write:
btn.setIcon( self.pixFindWrite )
else:
btn.setIcon( self.pixFindRead )
btn.setIconSize(buttonIconSize)
if databaseUserLevel > neuroConfig.userLevel:
btn.hide()
self.connect( btn, SIGNAL( 'clicked()' ), self.findPressed )
hb.addWidget( btn )
btn = QPushButton( )
if write:
btn.setIcon( self.pixBrowseWrite )
else:
btn.setIcon( self.pixBrowseRead )
btn.setIconSize(buttonIconSize)
if browseUserLevel > neuroConfig.userLevel:
btn.hide()
self.connect( btn, SIGNAL( 'clicked()' ), self.browsePressed )
hb.addWidget( btn )
layout.addLayout( hb )
# self.editor = self.parameter.editor( self, self.name() )
# layout.addWidget( self.editor )
hb = QHBoxLayout()
hb.setSpacing(6)
hb.setContentsMargins( 6, 6, 6, 6 )
spacer = QSpacerItem(20,20,QSizePolicy.Expanding,QSizePolicy.Minimum)
hb.addItem( spacer )
btn =QPushButton( _t_('Ok') )
hb.addWidget( btn )
self.connect( btn, SIGNAL( 'clicked()' ), self._ok )
btn =QPushButton( _t_('Cancel') )
hb.addWidget( btn )
self.connect( btn, SIGNAL( 'clicked()' ), self._cancel )
layout.addLayout( hb )
neuroConfig.registerObject( self )
def closeEvent( self, event ):
neuroConfig.unregisterObject( self )
QWidget.closeEvent( self, event )
def _currentChanged( self, index ):
if index >= 0 and index < len( self.values ):
if self.values[ index ] :
self.sle.setValue( [ self.values[ index ].fullPath() ] )
else :
self.sle.setValue( None )
self.btnRemove.setEnabled( 1 )
if index > 0:
self.btnUp.setEnabled( 1 )
else:
self.btnUp.setEnabled( 0 )
if index < ( len( self.values ) - 1 ):
self.btnDown.setEnabled( 1 )
else:
self.btnDown.setEnabled( 0 )
else:
self.sle.setValue( None )
self.btnRemove.setEnabled( 0 )
self.btnUp.setEnabled( 0 )
self.btnDown.setEnabled( 0 )
def _add( self ):
try:
for v in map( self.parameter.findValue, self.sle.getValue() ):
self.values.append( v )
if v is None:
self.lbxValues.addItem( '<' + _t_('None') + '>' )
else:
self.lbxValues.addItem( v.fileName() )
self.lbxValues.setCurrentRow( len( self.values ) - 1 )
except:
showException( parent=self )
def _remove( self ):
index = self.lbxValues.currentRow()
del self.values[ index ]
self.lbxValues.takeItem( index )
def _up( self ):
index = self.lbxValues.currentRow()
tmp = self.values[ index ]
self.values[ index ] = self.values[ index - 1 ]
self.values[ index - 1 ] = tmp
item=self.lbxValues.takeItem(index)
self.lbxValues.insertItem(index-1, item)
self.lbxValues.setCurrentRow(index-1)
def _down( self ):
index = self.lbxValues.currentRow()
tmp = self.values[ index ]
self.values[ index ] = self.values[ index + 1 ]
self.values[ index + 1 ] = tmp
item=self.lbxValues.takeItem(index)
self.lbxValues.insertItem(index+1, item)
self.lbxValues.setCurrentRow(index+1)
def setValue( self, value ):
if isinstance( value, ( list, tuple ) ):
self.values = []
self.lbxValues.clear()
for v in value:
self.values.append( v )
if v is None:
self.lbxValues.addItem( '<' + _t_('None') + '>' )
else:
self.lbxValues.addItem( v.fileName() )
def _ok( self ):
self.dilEditor._newValue( self.values )
self.close( )
def _cancel( self ):
self.close( )
def findPressed( self ):
if self.findDialog is None:
self.findDialog = DiskItemBrowser( self.parameter.database,
required=self.parameter.requiredAttributes,
parent=self,
write = self.parameter._write,
enableConversion=self.parameter.enableConversion,
multiple = True,
exactType=self.parameter.exactType )
self.connect( self.findDialog, SIGNAL( 'accepted()' ), self.findAccepted )
else:
self.findDialog.rescan()
self.findDialog.show()
def findAccepted( self ):
value = map( lambda x: x.fullPath(), self.findDialog.getValues() )
if self.isVisible():
self.sle.setValue( value )
self._add()
else:
self.emit( SIGNAL( 'accepted' ), value )
def browsePressed( self ):
if self.browseDialog is None:
self.browseDialog = QFileDialog( self.topLevelWidget() )
if not self.parameter._write :
self.browseDialog.setFileMode( self.browseDialog.ExistingFiles )
filters = []
allPatterns = {}
dirOnly = 1
formats = set( self.parameter.formats )
if self.parameter.enableConversion:
for t in [ self.parameter.type ] + self.parameter.type.parents():
for f in self.parameter.formats:
conv = brainvisa.processes.getConvertersTo( ( t, f ) )
for t2, f2 in conv.iterkeys():
formats.add( f2 )
for f in formats:
if f.fileOrDirectory() is not Directory:
dirOnly = 0
flt = f.getPatterns().unmatch( {}, { 'filename_variable': '*' } )[ 0 ]
allPatterns[ flt ] = 1
filters.append( _t_( f.name ) + ' (' + flt + ')' )
filters.insert( 0, _t_( 'Recognized formats' ) + ' (' \
+ ' '.join( allPatterns.keys() ) + ')' )
filters.append( _t_( 'All files' ) + ' (*)' )
self.browseDialog.setFilters( filters )
# self.connect( self.browseDialog, SIGNAL( 'fileSelected( const QString & )' ), self.browseAccepted )
self.connect( self.browseDialog, SIGNAL( 'accepted()' ), self.browseAccepted )
if dirOnly:
self.browseDialog.setFileMode( self.browseDialog.Directory )
parent = self._context
if hasattr( parent, '_currentDirectory' ) and parent._currentDirectory:
self.browseDialog.setDirectory( parent._currentDirectory )
else:
self.browseDialog.setDirectory( os.getcwd() )
self.browseDialog.show()
def browseAccepted( self ):
parent = self._context
if hasattr( parent, '_currentDirectory' ):
parent._currentDirectory = unicode( self.browseDialog.directory().path() )
l = [str(i) for i in self.browseDialog.selectedFiles()]
if self.isVisible():
self.sle.setValue( l )
self._add()
else:
self.emit( SIGNAL( 'accepted' ), l )
def __init__( self, parameter, parent, name, write = 0, context=None ):
if getattr( DiskItemListEditor, 'pixFindRead', None ) is None:
setattr( DiskItemListEditor, 'pixShow', QIcon( findIconFile( 'eye.png' )) )
setattr( DiskItemListEditor, 'pixEdit', QIcon( findIconFile( 'pencil.png' )) )
setattr( DiskItemListEditor, 'pixFindRead', QIcon( findIconFile( 'database_read.png' )) )
setattr( DiskItemListEditor, 'pixFindWrite', QIcon( findIconFile( 'database_write.png' )) )
setattr( DiskItemListEditor, 'pixBrowseRead', QIcon( findIconFile( 'browse_read.png' )) )
setattr( DiskItemListEditor, 'pixBrowseWrite', QIcon( findIconFile( 'browse_write.png' )) )
QWidget.__init__( self, parent )
if name:
self.setObjectName(name)
hb=QHBoxLayout()
self.setLayout(hb)
hb.setContentsMargins( 0, 0, 0, 0 )
hb.setSpacing(2)
self._context = context
self.parameter = parameter
self.write = write
self.sle = StringListEditor( None, name )
hb.addWidget(self.sle)
self._value = None
self.connect( self.sle, SIGNAL( 'newValidValue' ), self._newTextValue )
self.btnShow = RightClickablePushButton( )
hb.addWidget(self.btnShow)
self.btnShow.setCheckable(True)
self.btnShow.setIcon( self.pixShow )
self.btnShow.setIconSize(buttonIconSize)
self.btnShow.setFixedSize( buttonIconSize + buttonMargin )
self.btnShow.setFocusPolicy( Qt.NoFocus )
self.btnShow.setEnabled( False )
if not brainvisa.processes.getViewer( (self.parameter.type, self.parameter.formats[0] ), 0, checkUpdate=False, listof=True ):
self.btnShow.hide()
self._view = None
self.connect( self.btnShow, SIGNAL( 'clicked()' ), self.showPressed )
self.connect( self.btnShow, SIGNAL( 'rightPressed' ), self.openViewerPressed )
self._edit = None
self.btnEdit = RightClickablePushButton( )
hb.addWidget(self.btnEdit)
self.btnEdit.setCheckable(True)
self.btnEdit.setIcon( self.pixEdit )
self.btnEdit.setIconSize(buttonIconSize)
self.btnEdit.setFixedSize( buttonIconSize + buttonMargin )
self.btnEdit.setFocusPolicy( Qt.NoFocus )
self.btnEdit.setEnabled( 0 )
if not brainvisa.processes.getDataEditor( (self.parameter.type, self.parameter.formats ), checkUpdate=False, listof=True ):
self.btnEdit.hide()
self.connect( self.btnEdit, SIGNAL( 'clicked()' ), self.editPressed )
self.connect( self.btnEdit, SIGNAL( 'rightPressed' ),
self.openEditorPressed )
self.btnFind = RightClickablePushButton( )
hb.addWidget(self.btnFind)
if write:
self.btnFind.setIcon( self.pixFindWrite )
else:
self.btnFind.setIcon( self.pixFindRead )
self.btnFind.setIconSize(buttonIconSize)
self.btnFind.setFixedSize( buttonIconSize + buttonMargin )
self.btnFind.setFocusPolicy( Qt.NoFocus )
if hasattr( parameter, 'databaseUserLevel' ):
x = parameter.databaseUserLevel
if x > neuroConfig.userLevel:
self.btnFind.hide()
self.connect( self.btnFind, SIGNAL( 'clicked()' ), self.findPressed )
self.connect( self.btnFind, SIGNAL( 'rightPressed' ), self.findRightPressed )
self.btnBrowse = QPushButton( )
hb.addWidget(self.btnBrowse)
if write:
self.btnBrowse.setIcon( self.pixBrowseWrite )
else:
self.btnBrowse.setIcon( self.pixBrowseRead )
self.btnBrowse.setIconSize(buttonIconSize)
self.btnBrowse.setFixedSize( buttonIconSize + buttonMargin )
self.btnBrowse.setFocusPolicy( Qt.NoFocus )
if hasattr( parameter, 'browseUserLevel' ):
x = parameter.browseUserLevel
if x > neuroConfig.userLevel:
self.btnBrowse.hide()
# only one click on the browse button : always open the diskItemListSelect widget
# as we often need to select files in the filesystem in several steps when the files are not all in the same directory.
self.connect( self.btnBrowse, SIGNAL( 'clicked()' ), self.browsePressed )
#self.connect( self.btnBrowse, SIGNAL( 'rightPressed' ), self.browseRightPressed )
self.setValue( None, 1 )
def getValue( self ):
return self._value
def _setValue(self, value):
self._value=value
if isinstance( value, ( list, tuple ) ):
r = []
for v in value:
if v is None:
r.append( '' )
else:
r.append( str( v ) )
value = r
self.sle._setValue(value)
def setValue( self, value, default = 0 ):
self.forceDefault = default
self._value = value
if isinstance( value, ( list, tuple ) ):
r = []
for v in value:
if v is None:
r.append( '' )
else:
r.append( str( v ) )
value = r
if value:
self.checkReadable()
else:
if self.btnShow: self.btnShow.setEnabled( 0 )
if self.btnEdit: self.btnEdit.setEnabled( 0 )
self.sle.setValue( value, default )
self.forceDefault = 0
def checkReadable( self ):
if self.btnShow:
enabled = True
for v in self._value:
if not (v and isinstance(v, DiskItem) and v.isReadable()) :
enabled = False
self.btnShow.setEnabled( enabled )
if self.btnEdit:
enabled = True
for v in self._value:
if not (v and isinstance(v, DiskItem) and v.isWriteable()) :
enabled = False
self.btnEdit.setEnabled( enabled )
def showPressed( self ):
if self.btnShow.isChecked():
self.btnShow.setEnabled( 0 )
v = self.getValue()
try :
viewer = brainvisa.processes.getViewer( v, 0, listof=True )()
brainvisa.processes.defaultContext().runInteractiveProcess( self._viewerExited, viewer, v )
except Exception, error :
raise RuntimeError( HTMLMessage(_t_( 'No viewer could be found or launched for type =%s and format=%s' ) % (unicode( v.type ), unicode(v.format))) )
else:
self._view = None
def _viewerExited( self, result ):
if isinstance( result, Exception ):
showException( parent=self )
else:
self._view = result
neuroProcessesGUI.mainThreadActions().push( self.btnShow.setEnabled, 1 )
def openViewerPressed( self ):
v = self.getValue()
viewer = brainvisa.processes.getViewer( v, 0, listof=True )()
neuroProcessesGUI.showProcess( viewer, v )
def editPressed( self ):
if self.btnEdit.isChecked():
self.btnEdit.setEnabled( 0 )
v = self.getValue()
editor = brainvisa.processes.getDataEditor( v, listof=True )()
brainvisa.processes.defaultContext().runInteractiveProcess( self._editorExited, editor, v )
else:
self._edit = None
def _editorExited( self, result ):
if isinstance( result, Exception ):
showException( parent=self )
else:
self._edit = result
neuroProcessesGUI.mainThreadActions().push( self.btnEdit.setEnabled, True )
neuroProcessesGUI.mainThreadActions().push( self.btnEdit.setChecked, False )
def openEditorPressed( self ):
v = self.getValue()
editor = brainvisa.processes.getDataEditor( v, listof=True )()
neuroProcessesGUI.showProcess( editor, v )
def findPressed( self ):
dul = 0
bul = 0
if hasattr( self.parameter, 'databaseUserLevel' ):
dul = self.parameter.databaseUserLevel
if hasattr( self.parameter, 'browseUserLevel' ):
bul = self.parameter.browseUserLevel
w = self.DiskItemListSelect( self, unicode(self.objectName()), self.write,
databaseUserLevel=dul, browseUserLevel=bul )
try:
w.setValue( self.getValue() )
except:
showException( parent = self )
self.connect( w, SIGNAL( 'accepted' ), self._newValue )
w.findPressed()
def findRightPressed( self ):
dul = 0
bul = 0
if hasattr( self.parameter, 'databaseUserLevel' ):
dul = self.parameter.databaseUserLevel
if hasattr( self.parameter, 'browseUserLevel' ):
bul = self.parameter.browseUserLevel
w = self.DiskItemListSelect( self, unicode(self.objectName()), self.write,
databaseUserLevel=dul, browseUserLevel=bul )
try:
w.setValue( self.getValue() )
except:
showException( parent = self )
w.show()
w.findPressed()
#def browsePressed( self ):
#dul = 0
#bul = 0
#if hasattr( self.parameter, 'databaseUserLevel' ):
#dul = self.parameter.databaseUserLevel
#if hasattr( self.parameter, 'browseUserLevel' ):
#bul = self.parameter.browseUserLevel
#w = self.DiskItemListSelect( self, unicode(self.objectName()), self.write,
#context = self._context, databaseUserLevel=dul, browseUserLevel=bul )
#try:
#w.setValue( self.getValue() )
#except:
#showException( parent = self )
#self.connect( w, SIGNAL( 'accepted' ), self._newValue )
#w.browsePressed()
def browsePressed( self ):
dul = 0
bul = 0
if hasattr( self.parameter, 'databaseUserLevel' ):
dul = self.parameter.databaseUserLevel
if hasattr( self.parameter, 'browseUserLevel' ):
bul = self.parameter.browseUserLevel
w = self.DiskItemListSelect( self, unicode(self.objectName()), self.write,
context = self._context, databaseUserLevel=dul, browseUserLevel=bul )
try:
w.setValue( self.getValue() )
except:
showException( parent = self )
w.show()
w.browsePressed()
def _newTextValue( self ):
textValues = self.sle.getValue()
if textValues is not None:
self._newValue( [self.parameter.findValue( x ) for x in textValues] )
else:
self._newValue( None )
return None
def _newValue( self, v ):
self._setValue( v )
self.emit( SIGNAL('newValidValue'), unicode(self.objectName()), v )
if not self.forceDefault: self.emit( SIGNAL('noDefault'), unicode(self.objectName()) )
def checkValue( self ):
self.sle.checkValue()