Ejemplo n.º 1
0
class SVNPluginLogDialog( QDialog ):
    " SVN plugin log dialog "

    NODIFF = '<html><body bgcolor="#ffffe6"></body></html>'

    def __init__( self, plugin, client, path, logInfo, parent = None ):
        QDialog.__init__( self, parent )

        self.__plugin = plugin
        self.__client = client
        self.__path = path
        self.__logInfo = logInfo

        self.__lhsSelected = None
        self.__rhsSelected = None

        self.__createLayout()
        self.setWindowTitle( "SVN Log" )

        lastIndex = len( self.__logInfo ) - 1
        index = 0
        for log in self.__logInfo:
            newItem = LogItem( log )
            self.__logView.addTopLevelItem( newItem )

            if index != lastIndex:
                rev = log.revision.number
                nextRev = self.__logInfo[ index + 1 ].revision.number
                diffButton = self.__createDiffButton( log.revision,
                                                      self.__logInfo[ index + 1 ].revision )
                if rev is not None and nextRev is not None:
                    diffButton.setToolTip( "Click to see diff to the older revision (r." +
                                           str( rev ) + " to r." + str( nextRev ) + ")" )
                else:
                    diffButton.setEnabled( False )
                    diffButton.setToolTip( "Could not determine current or previous revision" )
            else:
                diffButton = self.__createDiffButton( None, None )
                diffButton.setEnabled( False )
                diffButton.setToolTip( "Diff to previous revision is not avalable for the first revision" )

            self.__logView.setItemWidget( newItem, DIFFTONEXT_COL, diffButton )
            index += 1

        self.__resizeLogView()
        self.__sortLogView()

        self.__logView.setFocus()
        return

    def __createDiffButton( self, rev, prevRev ):
        " Creates a diff button for a path "
        button = DiffButton()
        button.rev = rev
        button.prevRev = prevRev
        self.connect( button, SIGNAL( 'CustomClick' ), self.onDiffBetween )
        return button

    def __resizeLogView( self ):
        " Resizes the plugins table "
        self.__logView.header().setStretchLastSection( True )
        self.__logView.header().resizeSections(
                                        QHeaderView.ResizeToContents )
        self.__logView.header().resizeSection( SELECT_COL, 28 )
        self.__logView.header().setResizeMode( SELECT_COL, QHeaderView.Fixed )

        self.__logView.header().resizeSection( DIFFTONEXT_COL, 24 )
        self.__logView.header().setResizeMode( DIFFTONEXT_COL, QHeaderView.Fixed )
        return

    def __sortLogView( self ):
        " Sorts the log table "
        self.__logView.sortItems(
                    self.__logView.sortColumn(),
                    self.__logView.header().sortIndicatorOrder() )
        return

    def __createLayout( self ):
        " Creates the dialog layout "
        self.resize( 640, 480 )
        self.setSizeGripEnabled( True )

        vboxLayout = QVBoxLayout( self )

        # Revisions to compare
        compareGroupbox = QGroupBox( self )
        compareGroupbox.setTitle( "Revisions to compare" )
        sizePolicy = QSizePolicy( QSizePolicy.Expanding, QSizePolicy.Preferred )
        sizePolicy.setHorizontalStretch( 0 )
        sizePolicy.setVerticalStretch( 0 )
        sizePolicy.setHeightForWidth(
                        compareGroupbox.sizePolicy().hasHeightForWidth() )
        compareGroupbox.setSizePolicy( sizePolicy )

        revisionLayout = QHBoxLayout( compareGroupbox )

        self.__lhsRevisionLabel = QLabel()
        self.__lhsRevisionLabel.setFrameStyle( QFrame.StyledPanel )
        self.__lhsResetButton = QToolButton()
        self.__lhsResetButton.setIcon( PixmapCache().getIcon( pluginHomeDir + 'svnclearrev.png' ) )
        self.__lhsResetButton.setFocusPolicy( Qt.NoFocus )
        self.__lhsResetButton.setEnabled( False )
        self.__lhsResetButton.setToolTip( "Reset revision to compare" )
        self.__lhsResetButton.clicked.connect( self.__onLHSReset )
        self.__rhsRevisionLabel = QLabel()
        self.__rhsRevisionLabel.setFrameStyle( QFrame.StyledPanel )
        self.__rhsResetButton = QToolButton()
        self.__rhsResetButton.setIcon( PixmapCache().getIcon( pluginHomeDir + 'svnclearrev.png' ) )
        self.__rhsResetButton.setFocusPolicy( Qt.NoFocus )
        self.__rhsResetButton.setEnabled( False )
        self.__rhsResetButton.setToolTip( "Reset revision to compare" )
        self.__rhsResetButton.clicked.connect( self.__onRHSReset )

        lhsLayout = QHBoxLayout()
        lhsLayout.addWidget( self.__lhsRevisionLabel )
        lhsLayout.addWidget( self.__lhsResetButton )
        rhsLayout = QHBoxLayout()
        rhsLayout.addWidget( self.__rhsRevisionLabel )
        rhsLayout.addWidget( self.__rhsResetButton )
        bothLayout = QVBoxLayout()
        bothLayout.addLayout( lhsLayout )
        bothLayout.addLayout( rhsLayout )
        revisionLayout.addLayout( bothLayout )

        self.__diffButton = QToolButton()
        self.__diffButton.setText( "Diff" )
        self.__diffButton.setFocusPolicy( Qt.NoFocus )
        self.__diffButton.setEnabled( False )
        self.__diffButton.clicked.connect( self.__onDiff )
        revisionLayout.addWidget( self.__diffButton )
        vboxLayout.addWidget( compareGroupbox )

        # Log table
        logHeaderFrame = QFrame()
        logHeaderFrame.setFrameStyle( QFrame.StyledPanel )
        logHeaderFrame.setAutoFillBackground( True )
        self.__setLightPalette( logHeaderFrame )
        logHeaderFrame.setFixedHeight( 24 )

        logHeaderLayout = QHBoxLayout()
        logHeaderLayout.setContentsMargins( 3, 0, 0, 0 )
        logHeaderLayout.addWidget( QLabel( "Subversion log of " + self.__path ) )
        logHeaderFrame.setLayout( logHeaderLayout )
        vboxLayout.addWidget( logHeaderFrame )

        self.__logView = QTreeWidget()
        self.__logView.setAlternatingRowColors( True )
        self.__logView.setRootIsDecorated( False )
        self.__logView.setItemsExpandable( False )
        self.__logView.setSortingEnabled( True )
        self.__logView.setItemDelegate( NoOutlineHeightDelegate( 4 ) )

        self.__logViewHeader = QTreeWidgetItem( [ "", "", "Revision", "Date",
                                                  "Author", "Message" ] )
        self.__logView.setHeaderItem( self.__logViewHeader )
        self.__logView.header().setSortIndicator( REVISION_COL, Qt.AscendingOrder )
        self.__logView.itemChanged.connect( self.__onLogViewChanged )
        vboxLayout.addWidget( self.__logView )


        # Diff part
        diffHeaderFrame = QFrame()
        diffHeaderFrame.setFrameStyle( QFrame.StyledPanel )
        diffHeaderFrame.setAutoFillBackground( True )
        self.__setLightPalette( diffHeaderFrame )
        diffHeaderFrame.setFixedHeight( 24 )

        diffLabel = QLabel( "Diff" )
        diffExpandingSpacer = QSpacerItem( 10, 10, QSizePolicy.Expanding )

        self.__showHideDiffButton = QToolButton()
        self.__showHideDiffButton.setAutoRaise( True )
        self.__showHideDiffButton.setIcon( PixmapCache().getIcon( 'less.png' ) )
        self.__showHideDiffButton.setFixedSize( 20, 20 )
        self.__showHideDiffButton.setToolTip( "Show diff" )
        self.__showHideDiffButton.setFocusPolicy( Qt.NoFocus )
        self.__showHideDiffButton.clicked.connect( self.__onShowHideDiff )

        diffLayout = QHBoxLayout()
        diffLayout.setContentsMargins( 3, 0, 0, 0 )
        diffLayout.addWidget( diffLabel )
        diffLayout.addSpacerItem( diffExpandingSpacer )
        diffLayout.addWidget( self.__showHideDiffButton )
        diffHeaderFrame.setLayout( diffLayout )

        self.__diffViewer = DiffTabWidget()
        self.__diffViewer.setHTML( self.NODIFF )
        self.__diffViewer.setVisible( False )

        vboxLayout.addWidget( diffHeaderFrame )
        vboxLayout.addWidget( self.__diffViewer )

        # Buttons at the bottom
        buttonBox = QDialogButtonBox( self )
        buttonBox.setOrientation( Qt.Horizontal )
        buttonBox.setStandardButtons( QDialogButtonBox.Ok )
        buttonBox.button( QDialogButtonBox.Ok ).setDefault( True )
        buttonBox.accepted.connect( self.close )
        vboxLayout.addWidget( buttonBox )
        return

    @staticmethod
    def __setLightPalette( frame ):
        " Creates a lighter paletter for the widget background "
        palette = frame.palette()
        background = palette.color( QPalette.Background )
        background.setRgb( min( background.red() + 30, 255 ),
                           min( background.green() + 30, 255 ),
                           min( background.blue() + 30, 255 ) )
        palette.setColor( QPalette.Background, background )
        frame.setPalette( palette )
        return

    def __onShowHideDiff( self ):
        " On/off the diff section "
        if self.__diffViewer.isVisible():
            self.__diffViewer.setVisible( False )
            self.__showHideDiffButton.setIcon( PixmapCache().getIcon( 'less.png' ) )
            self.__showHideDiffButton.setToolTip( "Show diff" )
        else:
            self.__diffViewer.setVisible( True )
            self.__showHideDiffButton.setIcon( PixmapCache().getIcon( 'more.png' ) )
            self.__showHideDiffButton.setToolTip( "Hide diff" )
        return

    def onDiffBetween( self, rev, prevRev ):
        " Called when diff is requested between revisions "
        if not rev or not prevRev:
            return

        QApplication.setOverrideCursor( QCursor( Qt.WaitCursor ) )
        try:
            lhsContent = self.__client.cat( self.__path, prevRev )
            rhsContent = self.__client.cat( self.__path, rev )
        except Exception, exc:
            QApplication.restoreOverrideCursor()
            logging.error( str( exc ) )
            return
        except:
Ejemplo n.º 2
0
    def __createLayout( self ):
        " Creates the dialog layout "
        self.resize( 640, 480 )
        self.setSizeGripEnabled( True )

        vboxLayout = QVBoxLayout( self )

        # Revisions to compare
        compareGroupbox = QGroupBox( self )
        compareGroupbox.setTitle( "Revisions to compare" )
        sizePolicy = QSizePolicy( QSizePolicy.Expanding, QSizePolicy.Preferred )
        sizePolicy.setHorizontalStretch( 0 )
        sizePolicy.setVerticalStretch( 0 )
        sizePolicy.setHeightForWidth(
                        compareGroupbox.sizePolicy().hasHeightForWidth() )
        compareGroupbox.setSizePolicy( sizePolicy )

        revisionLayout = QHBoxLayout( compareGroupbox )

        self.__lhsRevisionLabel = QLabel()
        self.__lhsRevisionLabel.setFrameStyle( QFrame.StyledPanel )
        self.__lhsResetButton = QToolButton()
        self.__lhsResetButton.setIcon( PixmapCache().getIcon( pluginHomeDir + 'svnclearrev.png' ) )
        self.__lhsResetButton.setFocusPolicy( Qt.NoFocus )
        self.__lhsResetButton.setEnabled( False )
        self.__lhsResetButton.setToolTip( "Reset revision to compare" )
        self.__lhsResetButton.clicked.connect( self.__onLHSReset )
        self.__rhsRevisionLabel = QLabel()
        self.__rhsRevisionLabel.setFrameStyle( QFrame.StyledPanel )
        self.__rhsResetButton = QToolButton()
        self.__rhsResetButton.setIcon( PixmapCache().getIcon( pluginHomeDir + 'svnclearrev.png' ) )
        self.__rhsResetButton.setFocusPolicy( Qt.NoFocus )
        self.__rhsResetButton.setEnabled( False )
        self.__rhsResetButton.setToolTip( "Reset revision to compare" )
        self.__rhsResetButton.clicked.connect( self.__onRHSReset )

        lhsLayout = QHBoxLayout()
        lhsLayout.addWidget( self.__lhsRevisionLabel )
        lhsLayout.addWidget( self.__lhsResetButton )
        rhsLayout = QHBoxLayout()
        rhsLayout.addWidget( self.__rhsRevisionLabel )
        rhsLayout.addWidget( self.__rhsResetButton )
        bothLayout = QVBoxLayout()
        bothLayout.addLayout( lhsLayout )
        bothLayout.addLayout( rhsLayout )
        revisionLayout.addLayout( bothLayout )

        self.__diffButton = QToolButton()
        self.__diffButton.setText( "Diff" )
        self.__diffButton.setFocusPolicy( Qt.NoFocus )
        self.__diffButton.setEnabled( False )
        self.__diffButton.clicked.connect( self.__onDiff )
        revisionLayout.addWidget( self.__diffButton )
        vboxLayout.addWidget( compareGroupbox )

        # Log table
        logHeaderFrame = QFrame()
        logHeaderFrame.setFrameStyle( QFrame.StyledPanel )
        logHeaderFrame.setAutoFillBackground( True )
        self.__setLightPalette( logHeaderFrame )
        logHeaderFrame.setFixedHeight( 24 )

        logHeaderLayout = QHBoxLayout()
        logHeaderLayout.setContentsMargins( 3, 0, 0, 0 )
        logHeaderLayout.addWidget( QLabel( "Subversion log of " + self.__path ) )
        logHeaderFrame.setLayout( logHeaderLayout )
        vboxLayout.addWidget( logHeaderFrame )

        self.__logView = QTreeWidget()
        self.__logView.setAlternatingRowColors( True )
        self.__logView.setRootIsDecorated( False )
        self.__logView.setItemsExpandable( False )
        self.__logView.setSortingEnabled( True )
        self.__logView.setItemDelegate( NoOutlineHeightDelegate( 4 ) )

        self.__logViewHeader = QTreeWidgetItem( [ "", "", "Revision", "Date",
                                                  "Author", "Message" ] )
        self.__logView.setHeaderItem( self.__logViewHeader )
        self.__logView.header().setSortIndicator( REVISION_COL, Qt.AscendingOrder )
        self.__logView.itemChanged.connect( self.__onLogViewChanged )
        vboxLayout.addWidget( self.__logView )


        # Diff part
        diffHeaderFrame = QFrame()
        diffHeaderFrame.setFrameStyle( QFrame.StyledPanel )
        diffHeaderFrame.setAutoFillBackground( True )
        self.__setLightPalette( diffHeaderFrame )
        diffHeaderFrame.setFixedHeight( 24 )

        diffLabel = QLabel( "Diff" )
        diffExpandingSpacer = QSpacerItem( 10, 10, QSizePolicy.Expanding )

        self.__showHideDiffButton = QToolButton()
        self.__showHideDiffButton.setAutoRaise( True )
        self.__showHideDiffButton.setIcon( PixmapCache().getIcon( 'less.png' ) )
        self.__showHideDiffButton.setFixedSize( 20, 20 )
        self.__showHideDiffButton.setToolTip( "Show diff" )
        self.__showHideDiffButton.setFocusPolicy( Qt.NoFocus )
        self.__showHideDiffButton.clicked.connect( self.__onShowHideDiff )

        diffLayout = QHBoxLayout()
        diffLayout.setContentsMargins( 3, 0, 0, 0 )
        diffLayout.addWidget( diffLabel )
        diffLayout.addSpacerItem( diffExpandingSpacer )
        diffLayout.addWidget( self.__showHideDiffButton )
        diffHeaderFrame.setLayout( diffLayout )

        self.__diffViewer = DiffTabWidget()
        self.__diffViewer.setHTML( self.NODIFF )
        self.__diffViewer.setVisible( False )

        vboxLayout.addWidget( diffHeaderFrame )
        vboxLayout.addWidget( self.__diffViewer )

        # Buttons at the bottom
        buttonBox = QDialogButtonBox( self )
        buttonBox.setOrientation( Qt.Horizontal )
        buttonBox.setStandardButtons( QDialogButtonBox.Ok )
        buttonBox.button( QDialogButtonBox.Ok ).setDefault( True )
        buttonBox.accepted.connect( self.close )
        vboxLayout.addWidget( buttonBox )
        return
Ejemplo n.º 3
0
    def __createLayout(self, pathsToCommit, pathsToIgnore):
        " Creates the dialog layout "

        self.resize(640, 480)
        self.setSizeGripEnabled(True)

        vboxLayout = QVBoxLayout(self)

        # Paths to commit part
        commitHeaderFrame = QFrame()
        commitHeaderFrame.setFrameStyle(QFrame.StyledPanel)
        commitHeaderFrame.setAutoFillBackground(True)
        self.__setLightPalette(commitHeaderFrame)
        commitHeaderFrame.setFixedHeight(24)

        expandingCommitSpacer = QSpacerItem(10, 10, QSizePolicy.Expanding)

        self.__selectAllButton = QToolButton()
        self.__selectAllButton.setAutoRaise(True)
        self.__selectAllButton.setIcon(
            PixmapCache().getIcon(pluginHomeDir + 'svnselectall.png'))
        self.__selectAllButton.setFixedSize(20, 20)
        self.__selectAllButton.setToolTip("Select all")
        self.__selectAllButton.setFocusPolicy(Qt.NoFocus)
        self.__selectAllButton.clicked.connect(self.__onSelectAll)

        commitHeaderLayout = QHBoxLayout()
        commitHeaderLayout.setContentsMargins(3, 0, 0, 0)
        commitHeaderLayout.addWidget(
            QLabel("Paths to commit (total: " + str(len(pathsToCommit)) + ")"))
        commitHeaderLayout.addSpacerItem(expandingCommitSpacer)
        commitHeaderLayout.addWidget(self.__selectAllButton)
        commitHeaderFrame.setLayout(commitHeaderLayout)

        vboxLayout.addWidget(commitHeaderFrame)

        self.__pathToCommitView = QTreeWidget()
        self.__configTable(self.__pathToCommitView)

        self.__pathToCommitHeader = QTreeWidgetItem(["", "Path", "Status", ""])
        self.__pathToCommitView.setHeaderItem(self.__pathToCommitHeader)
        self.__pathToCommitView.header().setSortIndicator(
            PATH_COL, Qt.AscendingOrder)
        self.__pathToCommitView.itemChanged.connect(self.__onCommitPathChanged)
        vboxLayout.addWidget(self.__pathToCommitView)

        # Paths to ignore part
        headerFrame = QFrame()
        headerFrame.setFrameStyle(QFrame.StyledPanel)
        headerFrame.setAutoFillBackground(True)
        self.__setLightPalette(headerFrame)
        headerFrame.setFixedHeight(24)

        ignoreLabel = QLabel("Ignored paths (total: " +
                             str(len(pathsToIgnore)) + ")")
        expandingSpacer = QSpacerItem(10, 10, QSizePolicy.Expanding)

        self.__showHideIgnoredButton = QToolButton()
        self.__showHideIgnoredButton.setAutoRaise(True)
        self.__showHideIgnoredButton.setIcon(PixmapCache().getIcon('less.png'))
        self.__showHideIgnoredButton.setFixedSize(20, 20)
        self.__showHideIgnoredButton.setToolTip("Show ignored path list")
        self.__showHideIgnoredButton.setFocusPolicy(Qt.NoFocus)
        self.__showHideIgnoredButton.clicked.connect(self.__onShowHideIgnored)

        ignoredHeaderLayout = QHBoxLayout()
        ignoredHeaderLayout.setContentsMargins(3, 0, 0, 0)
        ignoredHeaderLayout.addWidget(ignoreLabel)
        ignoredHeaderLayout.addSpacerItem(expandingSpacer)
        ignoredHeaderLayout.addWidget(self.__showHideIgnoredButton)
        headerFrame.setLayout(ignoredHeaderLayout)

        vboxLayout.addWidget(headerFrame)

        self.__pathToIgnoreView = QTreeWidget()
        self.__configTable(self.__pathToIgnoreView)
        self.__pathToIgnoreView.setVisible(False)

        pathToIgnoreHeader = QTreeWidgetItem(["Path", "Status"])
        self.__pathToIgnoreView.setHeaderItem(pathToIgnoreHeader)
        self.__pathToIgnoreView.header().setSortIndicator(0, Qt.AscendingOrder)
        vboxLayout.addWidget(self.__pathToIgnoreView)

        # Message part
        vboxLayout.addWidget(QLabel("Message"))
        self.__message = QTextEdit()
        self.__message.setAcceptRichText(False)
        metrics = QFontMetrics(self.__message.font())
        rect = metrics.boundingRect("X")
        self.__message.setFixedHeight(rect.height() * 4 + 5)
        vboxLayout.addWidget(self.__message)

        # Diff part
        diffHeaderFrame = QFrame()
        diffHeaderFrame.setFrameStyle(QFrame.StyledPanel)
        diffHeaderFrame.setAutoFillBackground(True)
        self.__setLightPalette(diffHeaderFrame)
        diffHeaderFrame.setFixedHeight(24)

        diffLabel = QLabel("Diff")
        diffExpandingSpacer = QSpacerItem(10, 10, QSizePolicy.Expanding)

        self.__showHideDiffButton = QToolButton()
        self.__showHideDiffButton.setAutoRaise(True)
        self.__showHideDiffButton.setIcon(PixmapCache().getIcon('less.png'))
        self.__showHideDiffButton.setFixedSize(20, 20)
        self.__showHideDiffButton.setToolTip("Show diff")
        self.__showHideDiffButton.setFocusPolicy(Qt.NoFocus)
        self.__showHideDiffButton.clicked.connect(self.__onShowHideDiff)

        diffLayout = QHBoxLayout()
        diffLayout.setContentsMargins(3, 0, 0, 0)
        diffLayout.addWidget(diffLabel)
        diffLayout.addSpacerItem(diffExpandingSpacer)
        diffLayout.addWidget(self.__showHideDiffButton)
        diffHeaderFrame.setLayout(diffLayout)

        self.__diffViewer = DiffTabWidget()
        self.__diffViewer.setHTML(self.NODIFF)
        self.__diffViewer.setVisible(False)

        vboxLayout.addWidget(diffHeaderFrame)
        vboxLayout.addWidget(self.__diffViewer)

        # Buttons at the bottom
        buttonBox = QDialogButtonBox(self)
        buttonBox.setOrientation(Qt.Horizontal)
        buttonBox.setStandardButtons(QDialogButtonBox.Ok
                                     | QDialogButtonBox.Cancel)
        self.__OKButton = buttonBox.button(QDialogButtonBox.Ok)
        self.__OKButton.setText("Commit")
        buttonBox.button(QDialogButtonBox.Cancel).setDefault(True)
        buttonBox.accepted.connect(self.userAccept)
        buttonBox.rejected.connect(self.close)
        vboxLayout.addWidget(buttonBox)
        return
Ejemplo n.º 4
0
class SVNPluginCommitDialog(QDialog):
    " SVN Plugin commit dialog "

    NODIFF = '<html><body bgcolor="#ffffe6"></body></html>'

    def __init__(self, plugin, pathsToCommit, pathsToIgnore, parent=None):
        QDialog.__init__(self, parent)

        self.__plugin = plugin

        self.__createLayout(pathsToCommit, pathsToIgnore)
        self.setWindowTitle("SVN commit")

        # Fill the lists
        for item in pathsToCommit:
            newItem = QTreeWidgetItem(["", item[0], STATUS[item[1]]])
            newItem.setCheckState(CHECK_COL, Qt.Checked)
            newItem.setToolTip(PATH_COL, item[0])
            newItem.setToolTip(STATUS_COL, STATUS[item[1]])
            self.__pathToCommitView.addTopLevelItem(newItem)

            diffButton = self.__createDiffButton()
            diffButton.path = item[0]
            diffButton.status = item[1]

            fileType = detectFileType(item[0])

            if os.path.isdir( item[ 0 ] ) or item[ 1 ] in [ IND_REPLACED ] \
                or not isFileTypeSearchable( fileType ):
                diffButton.setEnabled(False)
                diffButton.setToolTip("Diff is not available")
            else:
                diffButton.setEnabled(True)
                diffButton.setToolTip("Click to see diff")
            self.__pathToCommitView.setItemWidget(newItem, DIFF_COL,
                                                  diffButton)

        self.__resizeCommitPaths()
        self.__sortCommitPaths()

        for item in pathsToIgnore:
            newItem = QTreeWidgetItem([item[0], STATUS[item[1]]])
            newItem.setToolTip(0, item[0])
            newItem.setToolTip(1, STATUS[item[1]])
            self.__pathToIgnoreView.addTopLevelItem(newItem)
        self.__pathToIgnoreView.header().resizeSections(
            QHeaderView.ResizeToContents)

        self.__updateSelectAllStatus()
        self.__updateOKStatus()
        self.__message.setFocus()
        return

    def __resizeCommitPaths(self):
        " Resizes the plugins table "
        self.__pathToCommitView.header().setStretchLastSection(False)
        self.__pathToCommitView.header().resizeSections(
            QHeaderView.ResizeToContents)
        self.__pathToCommitView.header().resizeSection(CHECK_COL, 28)
        self.__pathToCommitView.header().setResizeMode(CHECK_COL,
                                                       QHeaderView.Fixed)

        # By some reasons, to have PATH_COL visually adjustable the only STATUS_COL
        # must be set to be stretchable, so there is a comment below.
        # self.__pathToCommitView.header().setResizeMode( PATH_COL, QHeaderView.Stretch )
        self.__pathToCommitView.header().setResizeMode(STATUS_COL,
                                                       QHeaderView.Stretch)
        self.__pathToCommitView.header().resizeSection(DIFF_COL, 24)
        self.__pathToCommitView.header().setResizeMode(DIFF_COL,
                                                       QHeaderView.Fixed)
        return

    def __sortCommitPaths(self):
        " Sorts the commit paths table "
        self.__pathToCommitView.sortItems(
            self.__pathToCommitView.sortColumn(),
            self.__pathToCommitView.header().sortIndicatorOrder())
        return

    def __createDiffButton(self):
        " Creates a diff button for a path "
        button = DiffButton()
        self.connect(button, SIGNAL('CustomClick'), self.onDiff)
        return button

    @staticmethod
    def __setLightPalette(frame):
        " Creates a lighter paletter for the widget background "
        palette = frame.palette()
        background = palette.color(QPalette.Background)
        background.setRgb(min(background.red() + 30, 255),
                          min(background.green() + 30, 255),
                          min(background.blue() + 30, 255))
        palette.setColor(QPalette.Background, background)
        frame.setPalette(palette)
        return

    @staticmethod
    def __configTable(table):
        " Sets common properties for a table "
        table.setAlternatingRowColors(True)
        table.setRootIsDecorated(False)
        table.setItemsExpandable(False)
        table.setSortingEnabled(True)
        table.setItemDelegate(NoOutlineHeightDelegate(4))
        table.setUniformRowHeights(True)
        return

    def __createLayout(self, pathsToCommit, pathsToIgnore):
        " Creates the dialog layout "

        self.resize(640, 480)
        self.setSizeGripEnabled(True)

        vboxLayout = QVBoxLayout(self)

        # Paths to commit part
        commitHeaderFrame = QFrame()
        commitHeaderFrame.setFrameStyle(QFrame.StyledPanel)
        commitHeaderFrame.setAutoFillBackground(True)
        self.__setLightPalette(commitHeaderFrame)
        commitHeaderFrame.setFixedHeight(24)

        expandingCommitSpacer = QSpacerItem(10, 10, QSizePolicy.Expanding)

        self.__selectAllButton = QToolButton()
        self.__selectAllButton.setAutoRaise(True)
        self.__selectAllButton.setIcon(
            PixmapCache().getIcon(pluginHomeDir + 'svnselectall.png'))
        self.__selectAllButton.setFixedSize(20, 20)
        self.__selectAllButton.setToolTip("Select all")
        self.__selectAllButton.setFocusPolicy(Qt.NoFocus)
        self.__selectAllButton.clicked.connect(self.__onSelectAll)

        commitHeaderLayout = QHBoxLayout()
        commitHeaderLayout.setContentsMargins(3, 0, 0, 0)
        commitHeaderLayout.addWidget(
            QLabel("Paths to commit (total: " + str(len(pathsToCommit)) + ")"))
        commitHeaderLayout.addSpacerItem(expandingCommitSpacer)
        commitHeaderLayout.addWidget(self.__selectAllButton)
        commitHeaderFrame.setLayout(commitHeaderLayout)

        vboxLayout.addWidget(commitHeaderFrame)

        self.__pathToCommitView = QTreeWidget()
        self.__configTable(self.__pathToCommitView)

        self.__pathToCommitHeader = QTreeWidgetItem(["", "Path", "Status", ""])
        self.__pathToCommitView.setHeaderItem(self.__pathToCommitHeader)
        self.__pathToCommitView.header().setSortIndicator(
            PATH_COL, Qt.AscendingOrder)
        self.__pathToCommitView.itemChanged.connect(self.__onCommitPathChanged)
        vboxLayout.addWidget(self.__pathToCommitView)

        # Paths to ignore part
        headerFrame = QFrame()
        headerFrame.setFrameStyle(QFrame.StyledPanel)
        headerFrame.setAutoFillBackground(True)
        self.__setLightPalette(headerFrame)
        headerFrame.setFixedHeight(24)

        ignoreLabel = QLabel("Ignored paths (total: " +
                             str(len(pathsToIgnore)) + ")")
        expandingSpacer = QSpacerItem(10, 10, QSizePolicy.Expanding)

        self.__showHideIgnoredButton = QToolButton()
        self.__showHideIgnoredButton.setAutoRaise(True)
        self.__showHideIgnoredButton.setIcon(PixmapCache().getIcon('less.png'))
        self.__showHideIgnoredButton.setFixedSize(20, 20)
        self.__showHideIgnoredButton.setToolTip("Show ignored path list")
        self.__showHideIgnoredButton.setFocusPolicy(Qt.NoFocus)
        self.__showHideIgnoredButton.clicked.connect(self.__onShowHideIgnored)

        ignoredHeaderLayout = QHBoxLayout()
        ignoredHeaderLayout.setContentsMargins(3, 0, 0, 0)
        ignoredHeaderLayout.addWidget(ignoreLabel)
        ignoredHeaderLayout.addSpacerItem(expandingSpacer)
        ignoredHeaderLayout.addWidget(self.__showHideIgnoredButton)
        headerFrame.setLayout(ignoredHeaderLayout)

        vboxLayout.addWidget(headerFrame)

        self.__pathToIgnoreView = QTreeWidget()
        self.__configTable(self.__pathToIgnoreView)
        self.__pathToIgnoreView.setVisible(False)

        pathToIgnoreHeader = QTreeWidgetItem(["Path", "Status"])
        self.__pathToIgnoreView.setHeaderItem(pathToIgnoreHeader)
        self.__pathToIgnoreView.header().setSortIndicator(0, Qt.AscendingOrder)
        vboxLayout.addWidget(self.__pathToIgnoreView)

        # Message part
        vboxLayout.addWidget(QLabel("Message"))
        self.__message = QTextEdit()
        self.__message.setAcceptRichText(False)
        metrics = QFontMetrics(self.__message.font())
        rect = metrics.boundingRect("X")
        self.__message.setFixedHeight(rect.height() * 4 + 5)
        vboxLayout.addWidget(self.__message)

        # Diff part
        diffHeaderFrame = QFrame()
        diffHeaderFrame.setFrameStyle(QFrame.StyledPanel)
        diffHeaderFrame.setAutoFillBackground(True)
        self.__setLightPalette(diffHeaderFrame)
        diffHeaderFrame.setFixedHeight(24)

        diffLabel = QLabel("Diff")
        diffExpandingSpacer = QSpacerItem(10, 10, QSizePolicy.Expanding)

        self.__showHideDiffButton = QToolButton()
        self.__showHideDiffButton.setAutoRaise(True)
        self.__showHideDiffButton.setIcon(PixmapCache().getIcon('less.png'))
        self.__showHideDiffButton.setFixedSize(20, 20)
        self.__showHideDiffButton.setToolTip("Show diff")
        self.__showHideDiffButton.setFocusPolicy(Qt.NoFocus)
        self.__showHideDiffButton.clicked.connect(self.__onShowHideDiff)

        diffLayout = QHBoxLayout()
        diffLayout.setContentsMargins(3, 0, 0, 0)
        diffLayout.addWidget(diffLabel)
        diffLayout.addSpacerItem(diffExpandingSpacer)
        diffLayout.addWidget(self.__showHideDiffButton)
        diffHeaderFrame.setLayout(diffLayout)

        self.__diffViewer = DiffTabWidget()
        self.__diffViewer.setHTML(self.NODIFF)
        self.__diffViewer.setVisible(False)

        vboxLayout.addWidget(diffHeaderFrame)
        vboxLayout.addWidget(self.__diffViewer)

        # Buttons at the bottom
        buttonBox = QDialogButtonBox(self)
        buttonBox.setOrientation(Qt.Horizontal)
        buttonBox.setStandardButtons(QDialogButtonBox.Ok
                                     | QDialogButtonBox.Cancel)
        self.__OKButton = buttonBox.button(QDialogButtonBox.Ok)
        self.__OKButton.setText("Commit")
        buttonBox.button(QDialogButtonBox.Cancel).setDefault(True)
        buttonBox.accepted.connect(self.userAccept)
        buttonBox.rejected.connect(self.close)
        vboxLayout.addWidget(buttonBox)
        return

    def __onShowHideDiff(self):
        if self.__diffViewer.isVisible():
            self.__diffViewer.setVisible(False)
            self.__showHideDiffButton.setIcon(
                PixmapCache().getIcon('less.png'))
            self.__showHideDiffButton.setToolTip("Show diff")
        else:
            self.__diffViewer.setVisible(True)
            self.__showHideDiffButton.setIcon(
                PixmapCache().getIcon('more.png'))
            self.__showHideDiffButton.setToolTip("Hide diff")
        return

    def __onShowHideIgnored(self):
        if self.__pathToIgnoreView.isVisible():
            self.__pathToIgnoreView.setVisible(False)
            self.__showHideIgnoredButton.setIcon(
                PixmapCache().getIcon('less.png'))
            self.__showHideIgnoredButton.setToolTip("Show ignored path list")
        else:
            self.__pathToIgnoreView.setVisible(True)
            self.__showHideIgnoredButton.setIcon(
                PixmapCache().getIcon('more.png'))
            self.__showHideIgnoredButton.setToolTip("Hide ignored path list")
        return

    def userAccept(self):
        " Triggered when the user clicks OK "
        # Collect the list of checked paths
        self.commitMessage = self.__message.toPlainText().strip()

        self.commitPaths = []
        index = 0
        while index < self.__pathToCommitView.topLevelItemCount():
            item = self.__pathToCommitView.topLevelItem(index)
            if item.checkState(0) == Qt.Checked:
                path = str(item.text(1))
                if os.path.isdir( path ) and not os.path.islink( path ) and \
                                             not path.endswith( os.path.sep ):
                    path += os.path.sep
                self.commitPaths.append(path)
            index += 1
        self.accept()
        return

    def __getCheckedCount(self):
        " Provides the number of selected items in the commit paths section "
        index = 0
        checkedCount = 0
        while index < self.__pathToCommitView.topLevelItemCount():
            item = self.__pathToCommitView.topLevelItem(index)
            if item.checkState(0) == Qt.Checked:
                checkedCount += 1
            index += 1
        return checkedCount

    def __updateSelectAllStatus(self):
        " Updates the select all status button "
        total = self.__pathToCommitView.topLevelItemCount()
        if total == 0 or total == self.__getCheckedCount():
            self.__selectAllButton.setEnabled(False)
        else:
            self.__selectAllButton.setEnabled(True)
        return

    def __updateOKStatus(self):
        " Updates the OK button status "
        self.__OKButton.setEnabled(self.__getCheckedCount() > 0)
        return

    def __onCommitPathChanged(self, item, column):
        " Triggered when an item is changed "
        self.__updateSelectAllStatus()
        self.__updateOKStatus()
        return

    def __onSelectAll(self):
        " Triggered when select all button is clicked "
        index = 0
        while index < self.__pathToCommitView.topLevelItemCount():
            item = self.__pathToCommitView.topLevelItem(index)
            item.setCheckState(0, Qt.Checked)
            index += 1
        self.__updateSelectAllStatus()
        self.__updateOKStatus()
        return

    def onDiff(self, path, status):
        " Triggered when diff for the path is called "
        if not path:
            return

        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))

        try:
            # Status is one of the following:
            # IND_ADDED, IND_DELETED, IND_MERGED, IND_MODIFIED_LR, IND_MODIFIED_L, IND_CONFLICTED
            repositoryContent = ""
            localContent = ""
            if status != IND_ADDED:
                client = self.__plugin.getSVNClient(
                    self.__plugin.getSettings())
                repositoryContent = client.cat(path)
            if status != IND_DELETED:
                with open(path) as f:
                    localContent = f.read()

            diff = difflib.unified_diff(repositoryContent.splitlines(),
                                        localContent.splitlines())
            nodiffMessage = path + " has no difference to the " \
                                   "repository at revision HEAD"
            if diff is None:
                QApplication.restoreOverrideCursor()
                logging.info(nodiffMessage)
                return

            # There are changes, so replace the text and tell about the changes
            diffAsText = '\n'.join(list(diff))
            if diffAsText.strip() == '':
                QApplication.restoreOverrideCursor()
                logging.info(nodiffMessage)
                return

            source = "+++ local " + os.path.basename(path)
            diffAsText = diffAsText.replace("+++ ", source, 1)
            diffAsText = diffAsText.replace("--- ",
                                            "--- repository at revision HEAD",
                                            1)

            self.__diffViewer.setHTML(
                parse_from_memory(diffAsText, False, True))
            if not self.__diffViewer.isVisible():
                self.__onShowHideDiff()
        except Exception, exc:
            logging.error(str(exc))
        except:
Ejemplo n.º 5
0
    def __createLayout(self):
        " Creates the dialog layout "
        self.resize(640, 480)
        self.setSizeGripEnabled(True)

        vboxLayout = QVBoxLayout(self)

        # Revisions to compare
        compareGroupbox = QGroupBox(self)
        compareGroupbox.setTitle("Revisions to compare")
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            compareGroupbox.sizePolicy().hasHeightForWidth())
        compareGroupbox.setSizePolicy(sizePolicy)

        revisionLayout = QHBoxLayout(compareGroupbox)

        self.__lhsRevisionLabel = QLabel()
        self.__lhsRevisionLabel.setFrameStyle(QFrame.StyledPanel)
        self.__lhsResetButton = QToolButton()
        self.__lhsResetButton.setIcon(PixmapCache().getIcon(pluginHomeDir +
                                                            'svnclearrev.png'))
        self.__lhsResetButton.setFocusPolicy(Qt.NoFocus)
        self.__lhsResetButton.setEnabled(False)
        self.__lhsResetButton.setToolTip("Reset revision to compare")
        self.__lhsResetButton.clicked.connect(self.__onLHSReset)
        self.__rhsRevisionLabel = QLabel()
        self.__rhsRevisionLabel.setFrameStyle(QFrame.StyledPanel)
        self.__rhsResetButton = QToolButton()
        self.__rhsResetButton.setIcon(PixmapCache().getIcon(pluginHomeDir +
                                                            'svnclearrev.png'))
        self.__rhsResetButton.setFocusPolicy(Qt.NoFocus)
        self.__rhsResetButton.setEnabled(False)
        self.__rhsResetButton.setToolTip("Reset revision to compare")
        self.__rhsResetButton.clicked.connect(self.__onRHSReset)

        lhsLayout = QHBoxLayout()
        lhsLayout.addWidget(self.__lhsRevisionLabel)
        lhsLayout.addWidget(self.__lhsResetButton)
        rhsLayout = QHBoxLayout()
        rhsLayout.addWidget(self.__rhsRevisionLabel)
        rhsLayout.addWidget(self.__rhsResetButton)
        bothLayout = QVBoxLayout()
        bothLayout.addLayout(lhsLayout)
        bothLayout.addLayout(rhsLayout)
        revisionLayout.addLayout(bothLayout)

        self.__diffButton = QToolButton()
        self.__diffButton.setText("Diff")
        self.__diffButton.setFocusPolicy(Qt.NoFocus)
        self.__diffButton.setEnabled(False)
        self.__diffButton.clicked.connect(self.__onDiff)
        revisionLayout.addWidget(self.__diffButton)
        vboxLayout.addWidget(compareGroupbox)

        # Log table
        logHeaderFrame = QFrame()
        logHeaderFrame.setFrameStyle(QFrame.StyledPanel)
        logHeaderFrame.setAutoFillBackground(True)
        self.__setLightPalette(logHeaderFrame)
        logHeaderFrame.setFixedHeight(24)

        logHeaderLayout = QHBoxLayout()
        logHeaderLayout.setContentsMargins(3, 0, 0, 0)
        logHeaderLayout.addWidget(QLabel("Subversion log of " + self.__path))
        logHeaderFrame.setLayout(logHeaderLayout)
        vboxLayout.addWidget(logHeaderFrame)

        self.__logView = QTreeWidget()
        self.__logView.setAlternatingRowColors(True)
        self.__logView.setRootIsDecorated(False)
        self.__logView.setItemsExpandable(False)
        self.__logView.setSortingEnabled(True)
        self.__logView.setItemDelegate(NoOutlineHeightDelegate(4))

        self.__logViewHeader = QTreeWidgetItem(
            ["", "", "Revision", "Date", "Author", "Message"])
        self.__logView.setHeaderItem(self.__logViewHeader)
        self.__logView.header().setSortIndicator(REVISION_COL,
                                                 Qt.AscendingOrder)
        self.__logView.itemChanged.connect(self.__onLogViewChanged)
        vboxLayout.addWidget(self.__logView)

        # Diff part
        diffHeaderFrame = QFrame()
        diffHeaderFrame.setFrameStyle(QFrame.StyledPanel)
        diffHeaderFrame.setAutoFillBackground(True)
        self.__setLightPalette(diffHeaderFrame)
        diffHeaderFrame.setFixedHeight(24)

        diffLabel = QLabel("Diff")
        diffExpandingSpacer = QSpacerItem(10, 10, QSizePolicy.Expanding)

        self.__showHideDiffButton = QToolButton()
        self.__showHideDiffButton.setAutoRaise(True)
        self.__showHideDiffButton.setIcon(PixmapCache().getIcon('less.png'))
        self.__showHideDiffButton.setFixedSize(20, 20)
        self.__showHideDiffButton.setToolTip("Show diff")
        self.__showHideDiffButton.setFocusPolicy(Qt.NoFocus)
        self.__showHideDiffButton.clicked.connect(self.__onShowHideDiff)

        diffLayout = QHBoxLayout()
        diffLayout.setContentsMargins(3, 0, 0, 0)
        diffLayout.addWidget(diffLabel)
        diffLayout.addSpacerItem(diffExpandingSpacer)
        diffLayout.addWidget(self.__showHideDiffButton)
        diffHeaderFrame.setLayout(diffLayout)

        self.__diffViewer = DiffTabWidget()
        self.__diffViewer.setHTML(self.NODIFF)
        self.__diffViewer.setVisible(False)

        vboxLayout.addWidget(diffHeaderFrame)
        vboxLayout.addWidget(self.__diffViewer)

        # Buttons at the bottom
        buttonBox = QDialogButtonBox(self)
        buttonBox.setOrientation(Qt.Horizontal)
        buttonBox.setStandardButtons(QDialogButtonBox.Ok)
        buttonBox.button(QDialogButtonBox.Ok).setDefault(True)
        buttonBox.accepted.connect(self.close)
        vboxLayout.addWidget(buttonBox)
        return
Ejemplo n.º 6
0
class SVNPluginLogDialog(QDialog):
    " SVN plugin log dialog "

    NODIFF = '<html><body bgcolor="#ffffe6"></body></html>'

    def __init__(self, plugin, client, path, logInfo, parent=None):
        QDialog.__init__(self, parent)

        self.__plugin = plugin
        self.__client = client
        self.__path = path
        self.__logInfo = logInfo

        self.__lhsSelected = None
        self.__rhsSelected = None

        self.__createLayout()
        self.setWindowTitle("SVN Log")

        lastIndex = len(self.__logInfo) - 1
        index = 0
        for log in self.__logInfo:
            newItem = LogItem(log)
            self.__logView.addTopLevelItem(newItem)

            if index != lastIndex:
                rev = log.revision.number
                nextRev = self.__logInfo[index + 1].revision.number
                diffButton = self.__createDiffButton(
                    log.revision, self.__logInfo[index + 1].revision)
                if rev is not None and nextRev is not None:
                    diffButton.setToolTip(
                        "Click to see diff to the older revision (r." +
                        str(rev) + " to r." + str(nextRev) + ")")
                else:
                    diffButton.setEnabled(False)
                    diffButton.setToolTip(
                        "Could not determine current or previous revision")
            else:
                diffButton = self.__createDiffButton(None, None)
                diffButton.setEnabled(False)
                diffButton.setToolTip(
                    "Diff to previous revision is not avalable for the first revision"
                )

            self.__logView.setItemWidget(newItem, DIFFTONEXT_COL, diffButton)
            index += 1

        self.__resizeLogView()
        self.__sortLogView()

        self.__logView.setFocus()
        return

    def __createDiffButton(self, rev, prevRev):
        " Creates a diff button for a path "
        button = DiffButton()
        button.rev = rev
        button.prevRev = prevRev
        self.connect(button, SIGNAL('CustomClick'), self.onDiffBetween)
        return button

    def __resizeLogView(self):
        " Resizes the plugins table "
        self.__logView.header().setStretchLastSection(True)
        self.__logView.header().resizeSections(QHeaderView.ResizeToContents)
        self.__logView.header().resizeSection(SELECT_COL, 28)
        self.__logView.header().setResizeMode(SELECT_COL, QHeaderView.Fixed)

        self.__logView.header().resizeSection(DIFFTONEXT_COL, 24)
        self.__logView.header().setResizeMode(DIFFTONEXT_COL,
                                              QHeaderView.Fixed)
        return

    def __sortLogView(self):
        " Sorts the log table "
        self.__logView.sortItems(self.__logView.sortColumn(),
                                 self.__logView.header().sortIndicatorOrder())
        return

    def __createLayout(self):
        " Creates the dialog layout "
        self.resize(640, 480)
        self.setSizeGripEnabled(True)

        vboxLayout = QVBoxLayout(self)

        # Revisions to compare
        compareGroupbox = QGroupBox(self)
        compareGroupbox.setTitle("Revisions to compare")
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            compareGroupbox.sizePolicy().hasHeightForWidth())
        compareGroupbox.setSizePolicy(sizePolicy)

        revisionLayout = QHBoxLayout(compareGroupbox)

        self.__lhsRevisionLabel = QLabel()
        self.__lhsRevisionLabel.setFrameStyle(QFrame.StyledPanel)
        self.__lhsResetButton = QToolButton()
        self.__lhsResetButton.setIcon(PixmapCache().getIcon(pluginHomeDir +
                                                            'svnclearrev.png'))
        self.__lhsResetButton.setFocusPolicy(Qt.NoFocus)
        self.__lhsResetButton.setEnabled(False)
        self.__lhsResetButton.setToolTip("Reset revision to compare")
        self.__lhsResetButton.clicked.connect(self.__onLHSReset)
        self.__rhsRevisionLabel = QLabel()
        self.__rhsRevisionLabel.setFrameStyle(QFrame.StyledPanel)
        self.__rhsResetButton = QToolButton()
        self.__rhsResetButton.setIcon(PixmapCache().getIcon(pluginHomeDir +
                                                            'svnclearrev.png'))
        self.__rhsResetButton.setFocusPolicy(Qt.NoFocus)
        self.__rhsResetButton.setEnabled(False)
        self.__rhsResetButton.setToolTip("Reset revision to compare")
        self.__rhsResetButton.clicked.connect(self.__onRHSReset)

        lhsLayout = QHBoxLayout()
        lhsLayout.addWidget(self.__lhsRevisionLabel)
        lhsLayout.addWidget(self.__lhsResetButton)
        rhsLayout = QHBoxLayout()
        rhsLayout.addWidget(self.__rhsRevisionLabel)
        rhsLayout.addWidget(self.__rhsResetButton)
        bothLayout = QVBoxLayout()
        bothLayout.addLayout(lhsLayout)
        bothLayout.addLayout(rhsLayout)
        revisionLayout.addLayout(bothLayout)

        self.__diffButton = QToolButton()
        self.__diffButton.setText("Diff")
        self.__diffButton.setFocusPolicy(Qt.NoFocus)
        self.__diffButton.setEnabled(False)
        self.__diffButton.clicked.connect(self.__onDiff)
        revisionLayout.addWidget(self.__diffButton)
        vboxLayout.addWidget(compareGroupbox)

        # Log table
        logHeaderFrame = QFrame()
        logHeaderFrame.setFrameStyle(QFrame.StyledPanel)
        logHeaderFrame.setAutoFillBackground(True)
        self.__setLightPalette(logHeaderFrame)
        logHeaderFrame.setFixedHeight(24)

        logHeaderLayout = QHBoxLayout()
        logHeaderLayout.setContentsMargins(3, 0, 0, 0)
        logHeaderLayout.addWidget(QLabel("Subversion log of " + self.__path))
        logHeaderFrame.setLayout(logHeaderLayout)
        vboxLayout.addWidget(logHeaderFrame)

        self.__logView = QTreeWidget()
        self.__logView.setAlternatingRowColors(True)
        self.__logView.setRootIsDecorated(False)
        self.__logView.setItemsExpandable(False)
        self.__logView.setSortingEnabled(True)
        self.__logView.setItemDelegate(NoOutlineHeightDelegate(4))

        self.__logViewHeader = QTreeWidgetItem(
            ["", "", "Revision", "Date", "Author", "Message"])
        self.__logView.setHeaderItem(self.__logViewHeader)
        self.__logView.header().setSortIndicator(REVISION_COL,
                                                 Qt.AscendingOrder)
        self.__logView.itemChanged.connect(self.__onLogViewChanged)
        vboxLayout.addWidget(self.__logView)

        # Diff part
        diffHeaderFrame = QFrame()
        diffHeaderFrame.setFrameStyle(QFrame.StyledPanel)
        diffHeaderFrame.setAutoFillBackground(True)
        self.__setLightPalette(diffHeaderFrame)
        diffHeaderFrame.setFixedHeight(24)

        diffLabel = QLabel("Diff")
        diffExpandingSpacer = QSpacerItem(10, 10, QSizePolicy.Expanding)

        self.__showHideDiffButton = QToolButton()
        self.__showHideDiffButton.setAutoRaise(True)
        self.__showHideDiffButton.setIcon(PixmapCache().getIcon('less.png'))
        self.__showHideDiffButton.setFixedSize(20, 20)
        self.__showHideDiffButton.setToolTip("Show diff")
        self.__showHideDiffButton.setFocusPolicy(Qt.NoFocus)
        self.__showHideDiffButton.clicked.connect(self.__onShowHideDiff)

        diffLayout = QHBoxLayout()
        diffLayout.setContentsMargins(3, 0, 0, 0)
        diffLayout.addWidget(diffLabel)
        diffLayout.addSpacerItem(diffExpandingSpacer)
        diffLayout.addWidget(self.__showHideDiffButton)
        diffHeaderFrame.setLayout(diffLayout)

        self.__diffViewer = DiffTabWidget()
        self.__diffViewer.setHTML(self.NODIFF)
        self.__diffViewer.setVisible(False)

        vboxLayout.addWidget(diffHeaderFrame)
        vboxLayout.addWidget(self.__diffViewer)

        # Buttons at the bottom
        buttonBox = QDialogButtonBox(self)
        buttonBox.setOrientation(Qt.Horizontal)
        buttonBox.setStandardButtons(QDialogButtonBox.Ok)
        buttonBox.button(QDialogButtonBox.Ok).setDefault(True)
        buttonBox.accepted.connect(self.close)
        vboxLayout.addWidget(buttonBox)
        return

    @staticmethod
    def __setLightPalette(frame):
        " Creates a lighter paletter for the widget background "
        palette = frame.palette()
        background = palette.color(QPalette.Background)
        background.setRgb(min(background.red() + 30, 255),
                          min(background.green() + 30, 255),
                          min(background.blue() + 30, 255))
        palette.setColor(QPalette.Background, background)
        frame.setPalette(palette)
        return

    def __onShowHideDiff(self):
        " On/off the diff section "
        if self.__diffViewer.isVisible():
            self.__diffViewer.setVisible(False)
            self.__showHideDiffButton.setIcon(
                PixmapCache().getIcon('less.png'))
            self.__showHideDiffButton.setToolTip("Show diff")
        else:
            self.__diffViewer.setVisible(True)
            self.__showHideDiffButton.setIcon(
                PixmapCache().getIcon('more.png'))
            self.__showHideDiffButton.setToolTip("Hide diff")
        return

    def onDiffBetween(self, rev, prevRev):
        " Called when diff is requested between revisions "
        if not rev or not prevRev:
            return

        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
        try:
            lhsContent = self.__client.cat(self.__path, prevRev)
            rhsContent = self.__client.cat(self.__path, rev)
        except Exception, exc:
            QApplication.restoreOverrideCursor()
            logging.error(str(exc))
            return
        except:
Ejemplo n.º 7
0
class SVNPluginLogDialog(QDialog):
    """SVN plugin log dialog"""

    NODIFF = '<html><body bgcolor="#ffffe6"></body></html>'

    def __init__(self, plugin, client, path, logInfo, parent=None):
        QDialog.__init__(self, parent)

        self.__plugin = plugin
        self.__client = client
        self.__path = path
        self.__logInfo = logInfo

        self.__lhsSelected = None
        self.__rhsSelected = None

        self.__createLayout()
        self.setWindowTitle("SVN Log")

        lastIndex = len(self.__logInfo) - 1
        index = 0
        for log in self.__logInfo:
            newItem = LogItem(log)
            self.__logView.addTopLevelItem(newItem)

            if index != lastIndex:
                rev = log.revision.number
                nextRev = self.__logInfo[index + 1].revision.number
                diffButton = self.__createDiffButton(
                    log.revision, self.__logInfo[index + 1].revision)
                if rev is not None and nextRev is not None:
                    diffButton.setToolTip(
                        "Click to see diff to the older revision (r." +
                        str(rev) + " to r." + str(nextRev) + ")")
                else:
                    diffButton.setEnabled(False)
                    diffButton.setToolTip(
                        "Could not determine current or previous revision")
            else:
                diffButton = self.__createDiffButton(None, None)
                diffButton.setEnabled(False)
                diffButton.setToolTip(
                    "Diff to previous revision is not avalable for the first revision"
                )

            self.__logView.setItemWidget(newItem, DIFFTONEXT_COL, diffButton)
            index += 1

        self.__resizeLogView()
        self.__sortLogView()

        self.__logView.setFocus()

    def __createDiffButton(self, rev, prevRev):
        """Creates a diff button for a path"""
        button = DiffButton()
        button.rev = rev
        button.prevRev = prevRev
        self.connect(button, SIGNAL('CustomClick'), self.onDiffBetween)
        return button

    def __resizeLogView(self):
        """Resizes the plugins table"""
        self.__logView.header().setStretchLastSection(True)
        self.__logView.header().resizeSections(QHeaderView.ResizeToContents)
        self.__logView.header().resizeSection(SELECT_COL, 28)
        self.__logView.header().setResizeMode(SELECT_COL, QHeaderView.Fixed)

        self.__logView.header().resizeSection(DIFFTONEXT_COL, 24)
        self.__logView.header().setResizeMode(DIFFTONEXT_COL,
                                              QHeaderView.Fixed)

    def __sortLogView(self):
        """Sorts the log table"""
        self.__logView.sortItems(self.__logView.sortColumn(),
                                 self.__logView.header().sortIndicatorOrder())

    def __createLayout(self):
        """Creates the dialog layout"""
        self.resize(640, 480)
        self.setSizeGripEnabled(True)

        vboxLayout = QVBoxLayout(self)

        # Revisions to compare
        compareGroupbox = QGroupBox(self)
        compareGroupbox.setTitle("Revisions to compare")
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            compareGroupbox.sizePolicy().hasHeightForWidth())
        compareGroupbox.setSizePolicy(sizePolicy)

        revisionLayout = QHBoxLayout(compareGroupbox)

        self.__lhsRevisionLabel = QLabel()
        self.__lhsRevisionLabel.setFrameStyle(QFrame.StyledPanel)
        self.__lhsResetButton = QToolButton()
        self.__lhsResetButton.setIcon(
            getIcon(pluginHomeDir + 'svnclearrev.png'))
        self.__lhsResetButton.setFocusPolicy(Qt.NoFocus)
        self.__lhsResetButton.setEnabled(False)
        self.__lhsResetButton.setToolTip("Reset revision to compare")
        self.__lhsResetButton.clicked.connect(self.__onLHSReset)
        self.__rhsRevisionLabel = QLabel()
        self.__rhsRevisionLabel.setFrameStyle(QFrame.StyledPanel)
        self.__rhsResetButton = QToolButton()
        self.__rhsResetButton.setIcon(
            getIcon(pluginHomeDir + 'svnclearrev.png'))
        self.__rhsResetButton.setFocusPolicy(Qt.NoFocus)
        self.__rhsResetButton.setEnabled(False)
        self.__rhsResetButton.setToolTip("Reset revision to compare")
        self.__rhsResetButton.clicked.connect(self.__onRHSReset)

        lhsLayout = QHBoxLayout()
        lhsLayout.addWidget(self.__lhsRevisionLabel)
        lhsLayout.addWidget(self.__lhsResetButton)
        rhsLayout = QHBoxLayout()
        rhsLayout.addWidget(self.__rhsRevisionLabel)
        rhsLayout.addWidget(self.__rhsResetButton)
        bothLayout = QVBoxLayout()
        bothLayout.addLayout(lhsLayout)
        bothLayout.addLayout(rhsLayout)
        revisionLayout.addLayout(bothLayout)

        self.__diffButton = QToolButton()
        self.__diffButton.setText("Diff")
        self.__diffButton.setFocusPolicy(Qt.NoFocus)
        self.__diffButton.setEnabled(False)
        self.__diffButton.clicked.connect(self.__onDiff)
        revisionLayout.addWidget(self.__diffButton)
        vboxLayout.addWidget(compareGroupbox)

        # Log table
        logHeaderFrame = QFrame()
        logHeaderFrame.setFrameStyle(QFrame.StyledPanel)
        logHeaderFrame.setAutoFillBackground(True)
        self.__setLightPalette(logHeaderFrame)
        logHeaderFrame.setFixedHeight(24)

        logHeaderLayout = QHBoxLayout()
        logHeaderLayout.setContentsMargins(3, 0, 0, 0)
        logHeaderLayout.addWidget(QLabel("Subversion log of " + self.__path))
        logHeaderFrame.setLayout(logHeaderLayout)
        vboxLayout.addWidget(logHeaderFrame)

        self.__logView = QTreeWidget()
        self.__logView.setAlternatingRowColors(True)
        self.__logView.setRootIsDecorated(False)
        self.__logView.setItemsExpandable(False)
        self.__logView.setSortingEnabled(True)
        self.__logView.setItemDelegate(NoOutlineHeightDelegate(4))

        self.__logViewHeader = QTreeWidgetItem(
            ["", "", "Revision", "Date", "Author", "Message"])
        self.__logView.setHeaderItem(self.__logViewHeader)
        self.__logView.header().setSortIndicator(REVISION_COL,
                                                 Qt.AscendingOrder)
        self.__logView.itemChanged.connect(self.__onLogViewChanged)
        vboxLayout.addWidget(self.__logView)

        # Diff part
        diffHeaderFrame = QFrame()
        diffHeaderFrame.setFrameStyle(QFrame.StyledPanel)
        diffHeaderFrame.setAutoFillBackground(True)
        self.__setLightPalette(diffHeaderFrame)
        diffHeaderFrame.setFixedHeight(24)

        diffLabel = QLabel("Diff")
        diffExpandingSpacer = QSpacerItem(10, 10, QSizePolicy.Expanding)

        self.__showHideDiffButton = QToolButton()
        self.__showHideDiffButton.setAutoRaise(True)
        self.__showHideDiffButton.setIcon(getIcon('less.png'))
        self.__showHideDiffButton.setFixedSize(20, 20)
        self.__showHideDiffButton.setToolTip("Show diff")
        self.__showHideDiffButton.setFocusPolicy(Qt.NoFocus)
        self.__showHideDiffButton.clicked.connect(self.__onShowHideDiff)

        diffLayout = QHBoxLayout()
        diffLayout.setContentsMargins(3, 0, 0, 0)
        diffLayout.addWidget(diffLabel)
        diffLayout.addSpacerItem(diffExpandingSpacer)
        diffLayout.addWidget(self.__showHideDiffButton)
        diffHeaderFrame.setLayout(diffLayout)

        self.__diffViewer = DiffTabWidget()
        self.__diffViewer.setHTML(self.NODIFF)
        self.__diffViewer.setVisible(False)

        vboxLayout.addWidget(diffHeaderFrame)
        vboxLayout.addWidget(self.__diffViewer)

        # Buttons at the bottom
        buttonBox = QDialogButtonBox(self)
        buttonBox.setOrientation(Qt.Horizontal)
        buttonBox.setStandardButtons(QDialogButtonBox.Ok)
        buttonBox.button(QDialogButtonBox.Ok).setDefault(True)
        buttonBox.accepted.connect(self.close)
        vboxLayout.addWidget(buttonBox)

    @staticmethod
    def __setLightPalette(frame):
        """Creates a lighter palette for the widget background"""
        palette = frame.palette()
        background = palette.color(QPalette.Background)
        background.setRgb(min(background.red() + 30, 255),
                          min(background.green() + 30, 255),
                          min(background.blue() + 30, 255))
        palette.setColor(QPalette.Background, background)
        frame.setPalette(palette)

    def __onShowHideDiff(self):
        """On/off the diff section"""
        if self.__diffViewer.isVisible():
            self.__diffViewer.setVisible(False)
            self.__showHideDiffButton.setIcon(getIcon('less.png'))
            self.__showHideDiffButton.setToolTip("Show diff")
        else:
            self.__diffViewer.setVisible(True)
            self.__showHideDiffButton.setIcon(getIcon('more.png'))
            self.__showHideDiffButton.setToolTip("Hide diff")

    def onDiffBetween(self, rev, prevRev):
        """Called when diff is requested between revisions"""
        if not rev or not prevRev:
            return

        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
        try:
            lhsContent = self.__client.cat(self.__path, prevRev)
            rhsContent = self.__client.cat(self.__path, rev)
        except Exception as exc:
            QApplication.restoreOverrideCursor()
            logging.error(str(exc))
            return
        except:
            QApplication.restoreOverrideCursor()
            logging.error("Unknown error while retrieving " + self.__path +
                          " content from the repository.")
            return
        QApplication.restoreOverrideCursor()

        diff = difflib.unified_diff(lhsContent.splitlines(),
                                    rhsContent.splitlines())
        nodiffMessage = self.__path + " has no difference from revision " + \
            str(prevRev.number) + " to revision " + str(rev.number)
        if diff is None:
            logging.info(nodiffMessage)
            return

        # There are changes, so replace the text and tell about the changes
        diffAsText = '\n'.join(list(diff))
        if diffAsText.strip() == '':
            logging.info(nodiffMessage)
            return

        lhs = "--- revision " + str(prevRev.number)
        diffAsText = diffAsText.replace("--- ", lhs, 1)
        rhs = "+++ revision " + str(rev.number)
        diffAsText = diffAsText.replace("+++ ", rhs, 1)

        self.__diffViewer.setHTML(parse_from_memory(diffAsText, False, True))
        if not self.__diffViewer.isVisible():
            self.__onShowHideDiff()

    def __onDiff(self):
        """Show diff between revisions"""
        self.onDiffBetween(self.__rhsSelected.revision,
                           self.__lhsSelected.revision)

    def __onLogViewChanged(self, item, column):
        """Revision selected for diff"""
        if item.checkState(SELECT_COL) == Qt.Checked:
            # An item has been selected
            if self.__lhsSelected is None:
                self.__lhsSelected = item.logInfo
                self.__normalizeSelected()
                return
            if self.__rhsSelected is None:
                self.__rhsSelected = item.logInfo
                self.__normalizeSelected()
                return

            # Both of the places have been occupied. Pick the one to update.
            if item.logInfo.date > self.__rhsSelected.date:
                self.__rhsSelected = item.logInfo
            else:
                self.__lhsSelected = item.logInfo
            self.__normalizeSelected()
        else:
            # An item has been de-selected
            if self.__lhsSelected is not None:
                if self.__lhsSelected.revision.number == item.logInfo.revision.number:
                    self.__lhsSelected = None
            elif self.__rhsSelected is not None:
                if self.__rhsSelected.revision.number == item.logInfo.revision.number:
                    self.__rhsSelected = None
            self.__normalizeSelected()
        return

    def __onLHSReset(self):
        """Revision removed from diff"""
        if self.__lhsSelected is not None:
            self.__deselectRevision(self.__lhsSelected.revision.number)
        self.__lhsSelected = None
        self.__lhsRevisionLabel.setText("")
        self.__diffButton.setEnabled(False)
        self.__lhsResetButton.setEnabled(False)

    def __onRHSReset(self):
        """Revision removed from diff"""
        if self.__rhsSelected is not None:
            self.__deselectRevision(self.__rhsSelected.revision.number)
        self.__rhsSelected = None
        self.__rhsRevisionLabel.setText("")
        self.__diffButton.setEnabled(False)
        self.__rhsResetButton.setEnabled(False)

    def __deselectRevision(self, revNumber):
        """Deselects a revision in the list"""
        index = 0
        while index < self.__logView.topLevelItemCount():
            item = self.__logView.topLevelItem(index)
            if item.logInfo.revision.number == revNumber:
                item.setCheckState(SELECT_COL, Qt.Unchecked)
                break
            index += 1

    def __normalizeSelected(self):
        """Puts the earliest revision first"""
        if self.__lhsSelected is not None and self.__rhsSelected is not None:
            # It might be necessary to exchange the versions
            if self.__rhsSelected.date < self.__lhsSelected.date:
                temp = self.__rhsSelected
                self.__rhsSelected = self.__lhsSelected
                self.__lhsSelected = temp
            self.__diffButton.setEnabled(True)
        else:
            self.__diffButton.setEnabled(False)

        if self.__lhsSelected is None:
            self.__lhsRevisionLabel.setText("")
            self.__lhsRevisionLabel.setToolTip("")
            self.__lhsResetButton.setEnabled(False)
        else:
            self.__lhsRevisionLabel.setText(
                str(self.__lhsSelected.revision.number) + " (" +
                timestampToString(self.__lhsSelected.date) + ")")
            self.__lhsRevisionLabel.setToolTip(str(self.__lhsSelected.message))
            self.__lhsResetButton.setEnabled(True)

        if self.__rhsSelected is None:
            self.__rhsRevisionLabel.setText("")
            self.__rhsRevisionLabel.setToolTip("")
            self.__rhsResetButton.setEnabled(False)
        else:
            self.__rhsRevisionLabel.setText(
                str(self.__rhsSelected.revision.number) + " (" +
                timestampToString(self.__rhsSelected.date) + ")")
            self.__rhsRevisionLabel.setToolTip(str(self.__rhsSelected.message))
            self.__rhsResetButton.setEnabled(True)
Ejemplo n.º 8
0
class SVNPluginCommitDialog( QDialog ):
    " SVN Plugin commit dialog "

    NODIFF = '<html><body bgcolor="#ffffe6"></body></html>'

    def __init__( self, plugin, pathsToCommit, pathsToIgnore, parent = None ):
        QDialog.__init__( self, parent )

        self.__plugin = plugin

        self.__createLayout( pathsToCommit, pathsToIgnore )
        self.setWindowTitle( "SVN commit" )

        # Fill the lists
        for item in pathsToCommit:
            newItem = QTreeWidgetItem( [ "", item[ 0 ], STATUS[ item[ 1 ] ] ] )
            newItem.setCheckState( CHECK_COL, Qt.Checked )
            newItem.setToolTip( PATH_COL, item[ 0 ] )
            newItem.setToolTip( STATUS_COL, STATUS[ item[ 1 ] ] )
            self.__pathToCommitView.addTopLevelItem( newItem )

            diffButton = self.__createDiffButton()
            diffButton.path = item[ 0 ]
            diffButton.status = item[ 1 ]

            fileType = detectFileType( item[ 0 ] )

            if os.path.isdir( item[ 0 ] ) or item[ 1 ] in [ IND_REPLACED ] \
                or not isFileTypeSearchable( fileType ):
                diffButton.setEnabled( False )
                diffButton.setToolTip( "Diff is not available" )
            else:
                diffButton.setEnabled( True )
                diffButton.setToolTip( "Click to see diff" )
            self.__pathToCommitView.setItemWidget( newItem, DIFF_COL, diffButton )

        self.__resizeCommitPaths()
        self.__sortCommitPaths()

        for item in pathsToIgnore:
            newItem = QTreeWidgetItem( [ item[ 0 ], STATUS[ item[ 1 ] ] ] )
            newItem.setToolTip( 0, item[ 0 ] )
            newItem.setToolTip( 1, STATUS[ item[ 1 ] ] )
            self.__pathToIgnoreView.addTopLevelItem( newItem )
        self.__pathToIgnoreView.header().resizeSections( QHeaderView.ResizeToContents )

        self.__updateSelectAllStatus()
        self.__updateOKStatus()
        self.__message.setFocus()
        return

    def __resizeCommitPaths( self ):
        " Resizes the plugins table "
        self.__pathToCommitView.header().setStretchLastSection( False )
        self.__pathToCommitView.header().resizeSections(
                                        QHeaderView.ResizeToContents )
        self.__pathToCommitView.header().resizeSection( CHECK_COL, 28 )
        self.__pathToCommitView.header().setResizeMode( CHECK_COL, QHeaderView.Fixed )

        # By some reasons, to have PATH_COL visually adjustable the only STATUS_COL
        # must be set to be stretchable, so there is a comment below.
        # self.__pathToCommitView.header().setResizeMode( PATH_COL, QHeaderView.Stretch )
        self.__pathToCommitView.header().setResizeMode( STATUS_COL, QHeaderView.Stretch )
        self.__pathToCommitView.header().resizeSection( DIFF_COL, 24 )
        self.__pathToCommitView.header().setResizeMode( DIFF_COL, QHeaderView.Fixed )
        return

    def __sortCommitPaths( self ):
        " Sorts the commit paths table "
        self.__pathToCommitView.sortItems(
                    self.__pathToCommitView.sortColumn(),
                    self.__pathToCommitView.header().sortIndicatorOrder() )
        return

    def __createDiffButton( self ):
        " Creates a diff button for a path "
        button = DiffButton()
        self.connect( button, SIGNAL( 'CustomClick' ), self.onDiff )
        return button

    @staticmethod
    def __setLightPalette( frame ):
        " Creates a lighter paletter for the widget background "
        palette = frame.palette()
        background = palette.color( QPalette.Background )
        background.setRgb( min( background.red() + 30, 255 ),
                           min( background.green() + 30, 255 ),
                           min( background.blue() + 30, 255 ) )
        palette.setColor( QPalette.Background, background )
        frame.setPalette( palette )
        return

    @staticmethod
    def __configTable( table ):
        " Sets common properties for a table "
        table.setAlternatingRowColors( True )
        table.setRootIsDecorated( False )
        table.setItemsExpandable( False )
        table.setSortingEnabled( True )
        table.setItemDelegate( NoOutlineHeightDelegate( 4 ) )
        table.setUniformRowHeights( True )
        return

    def __createLayout( self, pathsToCommit, pathsToIgnore ):
        " Creates the dialog layout "

        self.resize( 640, 480 )
        self.setSizeGripEnabled( True )

        vboxLayout = QVBoxLayout( self )

        # Paths to commit part
        commitHeaderFrame = QFrame()
        commitHeaderFrame.setFrameStyle( QFrame.StyledPanel )
        commitHeaderFrame.setAutoFillBackground( True )
        self.__setLightPalette( commitHeaderFrame )
        commitHeaderFrame.setFixedHeight( 24 )

        expandingCommitSpacer = QSpacerItem( 10, 10, QSizePolicy.Expanding )

        self.__selectAllButton = QToolButton()
        self.__selectAllButton.setAutoRaise( True )
        self.__selectAllButton.setIcon( PixmapCache().getIcon( pluginHomeDir + 'svnselectall.png' ) )
        self.__selectAllButton.setFixedSize( 20, 20 )
        self.__selectAllButton.setToolTip( "Select all" )
        self.__selectAllButton.setFocusPolicy( Qt.NoFocus )
        self.__selectAllButton.clicked.connect( self.__onSelectAll )

        commitHeaderLayout = QHBoxLayout()
        commitHeaderLayout.setContentsMargins( 3, 0, 0, 0 )
        commitHeaderLayout.addWidget( QLabel( "Paths to commit (total: " +
                                              str( len( pathsToCommit ) ) + ")" ) )
        commitHeaderLayout.addSpacerItem( expandingCommitSpacer )
        commitHeaderLayout.addWidget( self.__selectAllButton )
        commitHeaderFrame.setLayout( commitHeaderLayout )

        vboxLayout.addWidget( commitHeaderFrame )

        self.__pathToCommitView = QTreeWidget()
        self.__configTable( self.__pathToCommitView )

        self.__pathToCommitHeader = QTreeWidgetItem( [ "", "Path", "Status", "" ] )
        self.__pathToCommitView.setHeaderItem( self.__pathToCommitHeader )
        self.__pathToCommitView.header().setSortIndicator( PATH_COL, Qt.AscendingOrder )
        self.__pathToCommitView.itemChanged.connect( self.__onCommitPathChanged )
        vboxLayout.addWidget( self.__pathToCommitView )

        # Paths to ignore part
        headerFrame = QFrame()
        headerFrame.setFrameStyle( QFrame.StyledPanel )
        headerFrame.setAutoFillBackground( True )
        self.__setLightPalette( headerFrame )
        headerFrame.setFixedHeight( 24 )

        ignoreLabel = QLabel( "Ignored paths (total: " +
                              str( len( pathsToIgnore ) ) + ")" )
        expandingSpacer = QSpacerItem( 10, 10, QSizePolicy.Expanding )

        self.__showHideIgnoredButton = QToolButton()
        self.__showHideIgnoredButton.setAutoRaise( True )
        self.__showHideIgnoredButton.setIcon( PixmapCache().getIcon( 'less.png' ) )
        self.__showHideIgnoredButton.setFixedSize( 20, 20 )
        self.__showHideIgnoredButton.setToolTip( "Show ignored path list" )
        self.__showHideIgnoredButton.setFocusPolicy( Qt.NoFocus )
        self.__showHideIgnoredButton.clicked.connect( self.__onShowHideIgnored )

        ignoredHeaderLayout = QHBoxLayout()
        ignoredHeaderLayout.setContentsMargins( 3, 0, 0, 0 )
        ignoredHeaderLayout.addWidget( ignoreLabel )
        ignoredHeaderLayout.addSpacerItem( expandingSpacer )
        ignoredHeaderLayout.addWidget( self.__showHideIgnoredButton )
        headerFrame.setLayout( ignoredHeaderLayout )

        vboxLayout.addWidget( headerFrame )

        self.__pathToIgnoreView = QTreeWidget()
        self.__configTable( self.__pathToIgnoreView )
        self.__pathToIgnoreView.setVisible( False )

        pathToIgnoreHeader = QTreeWidgetItem( [ "Path", "Status" ] )
        self.__pathToIgnoreView.setHeaderItem( pathToIgnoreHeader )
        self.__pathToIgnoreView.header().setSortIndicator( 0, Qt.AscendingOrder )
        vboxLayout.addWidget( self.__pathToIgnoreView )

        # Message part
        vboxLayout.addWidget( QLabel( "Message" ) )
        self.__message = QTextEdit()
        self.__message.setAcceptRichText( False )
        metrics = QFontMetrics( self.__message.font() )
        rect = metrics.boundingRect( "X" )
        self.__message.setFixedHeight( rect.height() * 4 + 5 )
        vboxLayout.addWidget( self.__message )

        # Diff part
        diffHeaderFrame = QFrame()
        diffHeaderFrame.setFrameStyle( QFrame.StyledPanel )
        diffHeaderFrame.setAutoFillBackground( True )
        self.__setLightPalette( diffHeaderFrame )
        diffHeaderFrame.setFixedHeight( 24 )

        diffLabel = QLabel( "Diff" )
        diffExpandingSpacer = QSpacerItem( 10, 10, QSizePolicy.Expanding )

        self.__showHideDiffButton = QToolButton()
        self.__showHideDiffButton.setAutoRaise( True )
        self.__showHideDiffButton.setIcon( PixmapCache().getIcon( 'less.png' ) )
        self.__showHideDiffButton.setFixedSize( 20, 20 )
        self.__showHideDiffButton.setToolTip( "Show diff" )
        self.__showHideDiffButton.setFocusPolicy( Qt.NoFocus )
        self.__showHideDiffButton.clicked.connect( self.__onShowHideDiff )

        diffLayout = QHBoxLayout()
        diffLayout.setContentsMargins( 3, 0, 0, 0 )
        diffLayout.addWidget( diffLabel )
        diffLayout.addSpacerItem( diffExpandingSpacer )
        diffLayout.addWidget( self.__showHideDiffButton )
        diffHeaderFrame.setLayout( diffLayout )

        self.__diffViewer = DiffTabWidget()
        self.__diffViewer.setHTML( self.NODIFF )
        self.__diffViewer.setVisible( False )

        vboxLayout.addWidget( diffHeaderFrame )
        vboxLayout.addWidget( self.__diffViewer )

        # Buttons at the bottom
        buttonBox = QDialogButtonBox( self )
        buttonBox.setOrientation( Qt.Horizontal )
        buttonBox.setStandardButtons( QDialogButtonBox.Ok |
                                      QDialogButtonBox.Cancel )
        self.__OKButton = buttonBox.button( QDialogButtonBox.Ok )
        self.__OKButton.setText( "Commit" )
        buttonBox.button( QDialogButtonBox.Cancel ).setDefault( True )
        buttonBox.accepted.connect( self.userAccept )
        buttonBox.rejected.connect( self.close )
        vboxLayout.addWidget( buttonBox )
        return

    def __onShowHideDiff( self ):
        if self.__diffViewer.isVisible():
            self.__diffViewer.setVisible( False )
            self.__showHideDiffButton.setIcon( PixmapCache().getIcon( 'less.png' ) )
            self.__showHideDiffButton.setToolTip( "Show diff" )
        else:
            self.__diffViewer.setVisible( True )
            self.__showHideDiffButton.setIcon( PixmapCache().getIcon( 'more.png' ) )
            self.__showHideDiffButton.setToolTip( "Hide diff" )
        return

    def __onShowHideIgnored( self ):
        if self.__pathToIgnoreView.isVisible():
            self.__pathToIgnoreView.setVisible( False )
            self.__showHideIgnoredButton.setIcon( PixmapCache().getIcon( 'less.png' ) )
            self.__showHideIgnoredButton.setToolTip( "Show ignored path list" )
        else:
            self.__pathToIgnoreView.setVisible( True )
            self.__showHideIgnoredButton.setIcon( PixmapCache().getIcon( 'more.png' ) )
            self.__showHideIgnoredButton.setToolTip( "Hide ignored path list" )
        return

    def userAccept( self ):
        " Triggered when the user clicks OK "
        # Collect the list of checked paths
        self.commitMessage = self.__message.toPlainText().strip()

        self.commitPaths = []
        index = 0
        while index < self.__pathToCommitView.topLevelItemCount():
            item = self.__pathToCommitView.topLevelItem( index )
            if item.checkState( 0 ) == Qt.Checked:
                path = str( item.text( 1 ) )
                if os.path.isdir( path ) and not os.path.islink( path ) and \
                                             not path.endswith( os.path.sep ):
                    path += os.path.sep
                self.commitPaths.append( path )
            index += 1
        self.accept()
        return

    def __getCheckedCount( self ):
        " Provides the number of selected items in the commit paths section "
        index = 0
        checkedCount = 0
        while index < self.__pathToCommitView.topLevelItemCount():
            item = self.__pathToCommitView.topLevelItem( index )
            if item.checkState( 0 ) == Qt.Checked:
                checkedCount += 1
            index += 1
        return checkedCount

    def __updateSelectAllStatus( self ):
        " Updates the select all status button "
        total = self.__pathToCommitView.topLevelItemCount()
        if total == 0 or total == self.__getCheckedCount():
            self.__selectAllButton.setEnabled( False )
        else:
            self.__selectAllButton.setEnabled( True )
        return

    def __updateOKStatus( self ):
        " Updates the OK button status "
        self.__OKButton.setEnabled( self.__getCheckedCount() > 0 )
        return

    def __onCommitPathChanged( self, item, column ):
        " Triggered when an item is changed "
        self.__updateSelectAllStatus()
        self.__updateOKStatus()
        return

    def __onSelectAll( self ):
        " Triggered when select all button is clicked "
        index = 0
        while index < self.__pathToCommitView.topLevelItemCount():
            item = self.__pathToCommitView.topLevelItem( index )
            item.setCheckState( 0, Qt.Checked )
            index += 1
        self.__updateSelectAllStatus()
        self.__updateOKStatus()
        return

    def onDiff( self, path, status ):
        " Triggered when diff for the path is called "
        if not path:
            return

        QApplication.setOverrideCursor( QCursor( Qt.WaitCursor ) )

        try:
            # Status is one of the following:
            # IND_ADDED, IND_DELETED, IND_MERGED, IND_MODIFIED_LR, IND_MODIFIED_L, IND_CONFLICTED
            repositoryContent = ""
            localContent = ""
            if status != IND_ADDED:
                client = self.__plugin.getSVNClient( self.__plugin.getSettings() )
                repositoryContent = client.cat( path )
            if status != IND_DELETED:
                with open( path ) as f:
                    localContent = f.read()

            diff = difflib.unified_diff( repositoryContent.splitlines(),
                                         localContent.splitlines() )
            nodiffMessage = path + " has no difference to the " \
                                   "repository at revision HEAD"
            if diff is None:
                QApplication.restoreOverrideCursor()
                logging.info( nodiffMessage )
                return

            # There are changes, so replace the text and tell about the changes
            diffAsText = '\n'.join( list( diff ) )
            if diffAsText.strip() == '':
                QApplication.restoreOverrideCursor()
                logging.info( nodiffMessage )
                return

            source = "+++ local " + os.path.basename( path )
            diffAsText = diffAsText.replace( "+++ ", source, 1 )
            diffAsText = diffAsText.replace( "--- ",
                                             "--- repository at revision HEAD", 1 )

            self.__diffViewer.setHTML( parse_from_memory( diffAsText, False, True ) )
            if not self.__diffViewer.isVisible():
                self.__onShowHideDiff()
        except Exception, exc:
            logging.error( str( exc ) )
        except:
Ejemplo n.º 9
0
    def __createLayout( self, pathsToCommit, pathsToIgnore ):
        " Creates the dialog layout "

        self.resize( 640, 480 )
        self.setSizeGripEnabled( True )

        vboxLayout = QVBoxLayout( self )

        # Paths to commit part
        commitHeaderFrame = QFrame()
        commitHeaderFrame.setFrameStyle( QFrame.StyledPanel )
        commitHeaderFrame.setAutoFillBackground( True )
        self.__setLightPalette( commitHeaderFrame )
        commitHeaderFrame.setFixedHeight( 24 )

        expandingCommitSpacer = QSpacerItem( 10, 10, QSizePolicy.Expanding )

        self.__selectAllButton = QToolButton()
        self.__selectAllButton.setAutoRaise( True )
        self.__selectAllButton.setIcon( PixmapCache().getIcon( pluginHomeDir + 'svnselectall.png' ) )
        self.__selectAllButton.setFixedSize( 20, 20 )
        self.__selectAllButton.setToolTip( "Select all" )
        self.__selectAllButton.setFocusPolicy( Qt.NoFocus )
        self.__selectAllButton.clicked.connect( self.__onSelectAll )

        commitHeaderLayout = QHBoxLayout()
        commitHeaderLayout.setContentsMargins( 3, 0, 0, 0 )
        commitHeaderLayout.addWidget( QLabel( "Paths to commit (total: " +
                                              str( len( pathsToCommit ) ) + ")" ) )
        commitHeaderLayout.addSpacerItem( expandingCommitSpacer )
        commitHeaderLayout.addWidget( self.__selectAllButton )
        commitHeaderFrame.setLayout( commitHeaderLayout )

        vboxLayout.addWidget( commitHeaderFrame )

        self.__pathToCommitView = QTreeWidget()
        self.__configTable( self.__pathToCommitView )

        self.__pathToCommitHeader = QTreeWidgetItem( [ "", "Path", "Status", "" ] )
        self.__pathToCommitView.setHeaderItem( self.__pathToCommitHeader )
        self.__pathToCommitView.header().setSortIndicator( PATH_COL, Qt.AscendingOrder )
        self.__pathToCommitView.itemChanged.connect( self.__onCommitPathChanged )
        vboxLayout.addWidget( self.__pathToCommitView )

        # Paths to ignore part
        headerFrame = QFrame()
        headerFrame.setFrameStyle( QFrame.StyledPanel )
        headerFrame.setAutoFillBackground( True )
        self.__setLightPalette( headerFrame )
        headerFrame.setFixedHeight( 24 )

        ignoreLabel = QLabel( "Ignored paths (total: " +
                              str( len( pathsToIgnore ) ) + ")" )
        expandingSpacer = QSpacerItem( 10, 10, QSizePolicy.Expanding )

        self.__showHideIgnoredButton = QToolButton()
        self.__showHideIgnoredButton.setAutoRaise( True )
        self.__showHideIgnoredButton.setIcon( PixmapCache().getIcon( 'less.png' ) )
        self.__showHideIgnoredButton.setFixedSize( 20, 20 )
        self.__showHideIgnoredButton.setToolTip( "Show ignored path list" )
        self.__showHideIgnoredButton.setFocusPolicy( Qt.NoFocus )
        self.__showHideIgnoredButton.clicked.connect( self.__onShowHideIgnored )

        ignoredHeaderLayout = QHBoxLayout()
        ignoredHeaderLayout.setContentsMargins( 3, 0, 0, 0 )
        ignoredHeaderLayout.addWidget( ignoreLabel )
        ignoredHeaderLayout.addSpacerItem( expandingSpacer )
        ignoredHeaderLayout.addWidget( self.__showHideIgnoredButton )
        headerFrame.setLayout( ignoredHeaderLayout )

        vboxLayout.addWidget( headerFrame )

        self.__pathToIgnoreView = QTreeWidget()
        self.__configTable( self.__pathToIgnoreView )
        self.__pathToIgnoreView.setVisible( False )

        pathToIgnoreHeader = QTreeWidgetItem( [ "Path", "Status" ] )
        self.__pathToIgnoreView.setHeaderItem( pathToIgnoreHeader )
        self.__pathToIgnoreView.header().setSortIndicator( 0, Qt.AscendingOrder )
        vboxLayout.addWidget( self.__pathToIgnoreView )

        # Message part
        vboxLayout.addWidget( QLabel( "Message" ) )
        self.__message = QTextEdit()
        self.__message.setAcceptRichText( False )
        metrics = QFontMetrics( self.__message.font() )
        rect = metrics.boundingRect( "X" )
        self.__message.setFixedHeight( rect.height() * 4 + 5 )
        vboxLayout.addWidget( self.__message )

        # Diff part
        diffHeaderFrame = QFrame()
        diffHeaderFrame.setFrameStyle( QFrame.StyledPanel )
        diffHeaderFrame.setAutoFillBackground( True )
        self.__setLightPalette( diffHeaderFrame )
        diffHeaderFrame.setFixedHeight( 24 )

        diffLabel = QLabel( "Diff" )
        diffExpandingSpacer = QSpacerItem( 10, 10, QSizePolicy.Expanding )

        self.__showHideDiffButton = QToolButton()
        self.__showHideDiffButton.setAutoRaise( True )
        self.__showHideDiffButton.setIcon( PixmapCache().getIcon( 'less.png' ) )
        self.__showHideDiffButton.setFixedSize( 20, 20 )
        self.__showHideDiffButton.setToolTip( "Show diff" )
        self.__showHideDiffButton.setFocusPolicy( Qt.NoFocus )
        self.__showHideDiffButton.clicked.connect( self.__onShowHideDiff )

        diffLayout = QHBoxLayout()
        diffLayout.setContentsMargins( 3, 0, 0, 0 )
        diffLayout.addWidget( diffLabel )
        diffLayout.addSpacerItem( diffExpandingSpacer )
        diffLayout.addWidget( self.__showHideDiffButton )
        diffHeaderFrame.setLayout( diffLayout )

        self.__diffViewer = DiffTabWidget()
        self.__diffViewer.setHTML( self.NODIFF )
        self.__diffViewer.setVisible( False )

        vboxLayout.addWidget( diffHeaderFrame )
        vboxLayout.addWidget( self.__diffViewer )

        # Buttons at the bottom
        buttonBox = QDialogButtonBox( self )
        buttonBox.setOrientation( Qt.Horizontal )
        buttonBox.setStandardButtons( QDialogButtonBox.Ok |
                                      QDialogButtonBox.Cancel )
        self.__OKButton = buttonBox.button( QDialogButtonBox.Ok )
        self.__OKButton.setText( "Commit" )
        buttonBox.button( QDialogButtonBox.Cancel ).setDefault( True )
        buttonBox.accepted.connect( self.userAccept )
        buttonBox.rejected.connect( self.close )
        vboxLayout.addWidget( buttonBox )
        return