# mq.py - TortoiseHg MQ widget
#
# Copyright 2011 Steve Borho <steve@borho.org>
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.

import os

from PyQt4.QtCore import *
from PyQt4.QtGui import *

from tortoisehg.util import hglib
from tortoisehg.hgqt.i18n import _
from tortoisehg.hgqt import cmdcore, qtlib, cmdui, thgrepo
from tortoisehg.hgqt import commit, qdelete, qrename, qreorder, mqutil
from tortoisehg.hgqt.qtlib import geticon

class QueueManagementActions(QObject):
    """Container for patch queue management actions"""

    def __init__(self, parent=None):
        super(QueueManagementActions, self).__init__(parent)
        assert parent is None or isinstance(parent, QWidget)
        self._repoagent = None
        self._cmdsession = cmdcore.nullCmdSession()

        self._actions = {
            'commitQueue': QAction(_('&Commit to Queue...'), self),
            'createQueue': QAction(_('Create &New Queue...'), self),
            'renameQueue': QAction(_('&Rename Active Queue...'), self),
            'deleteQueue': QAction(_('&Delete Queue...'), self),
            'purgeQueue':  QAction(_('&Purge Queue...'), self),
            }
        for name, action in self._actions.iteritems():
            action.triggered.connect(getattr(self, '_' + name))
        self._updateActions()

    def setRepoAgent(self, repoagent):
        self._repoagent = repoagent
        self._updateActions()

    def _updateActions(self):
        enabled = bool(self._repoagent) and self._cmdsession.isFinished()
        for action in self._actions.itervalues():
            action.setEnabled(enabled)

    def createMenu(self, parent=None):
        menu = QMenu(parent)
        menu.addAction(self._actions['commitQueue'])
        menu.addSeparator()
        for name in ['createQueue', 'renameQueue', 'deleteQueue', 'purgeQueue']:
            menu.addAction(self._actions[name])
        return menu

    @pyqtSlot()
    def _commitQueue(self):
        assert self._repoagent
        repo = self._repoagent.rawRepo()
        if os.path.isdir(repo.mq.join('.hg')):
            self._launchCommitDialog()
            return
        if not self._cmdsession.isFinished():
            return

        cmdline = hglib.buildcmdargs('init', mq=True)
        self._cmdsession = sess = self._repoagent.runCommand(cmdline, self)
        sess.commandFinished.connect(self._onQueueRepoInitialized)
        self._updateActions()

    @pyqtSlot(int)
    def _onQueueRepoInitialized(self, ret):
        if ret == 0:
            self._launchCommitDialog()
        self._onCommandFinished(ret)

    def _launchCommitDialog(self):
        if not self._repoagent:
            return
        repo = self._repoagent.rawRepo()
        # TODO: do not instantiate mqrepo here
        mqrepo = thgrepo.repository(None, repo.mq.path)
        repoagent = mqrepo._pyqtobj
        dlg = commit.CommitDialog(repoagent, [], {}, self.parent())
        dlg.finished.connect(dlg.deleteLater)
        dlg.exec_()

    def switchQueue(self, name):
        return self._runQqueue(None, name)

    @pyqtSlot()
    def _createQueue(self):
        name = self._getNewName(_('Create Patch Queue'),
                                _('New patch queue name'),
                                _('Create'))
        if name:
            self._runQqueue('create', name)

    @pyqtSlot()
    def _renameQueue(self):
        curname = self._activeName()
        newname = self._getNewName(_('Rename Patch Queue'),
                                   _("Rename patch queue '%s' to") % curname,
                                   _('Rename'))
        if newname and curname != newname:
            self._runQqueue('rename', newname)

    @pyqtSlot()
    def _deleteQueue(self):
        name = self._getExistingName(_('Delete Patch Queue'),
                                     _('Delete reference to'),
                                     _('Delete'))
        if name:
            self._runQqueueInactive('delete', name)

    @pyqtSlot()
    def _purgeQueue(self):
        name = self._getExistingName(_('Purge Patch Queue'),
                                     _('Remove patch directory of'),
                                     _('Purge'))
        if name:
            self._runQqueueInactive('purge', name)

    def _activeName(self):
        assert self._repoagent
        repo = self._repoagent.rawRepo()
        return hglib.tounicode(repo.thgactivemqname)

    def _existingNames(self):
        assert self._repoagent
        return mqutil.getQQueues(self._repoagent.rawRepo())

    def _getNewName(self, title, labeltext, oktext):
        dlg = QInputDialog(self.parent())
        dlg.setWindowTitle(title)
        dlg.setLabelText(labeltext)
        dlg.setOkButtonText(oktext)
        if dlg.exec_():
            return dlg.textValue()

    def _getExistingName(self, title, labeltext, oktext):
        dlg = QInputDialog(self.parent())
        dlg.setWindowTitle(title)
        dlg.setLabelText(labeltext)
        dlg.setOkButtonText(oktext)
        dlg.setComboBoxEditable(False)
        dlg.setComboBoxItems(self._existingNames())
        dlg.setTextValue(self._activeName())
        if dlg.exec_():
            return dlg.textValue()

    def abort(self):
        self._cmdsession.abort()

    def _runQqueue(self, op, name):
        """Execute qqueue operation against the specified queue"""
        assert self._repoagent
        if not self._cmdsession.isFinished():
            return cmdcore.nullCmdSession()

        opts = {}
        if op:
            opts[op] = True
        cmdline = hglib.buildcmdargs('qqueue', name, **opts)
        self._cmdsession = sess = self._repoagent.runCommand(cmdline, self)
        sess.commandFinished.connect(self._onCommandFinished)
        self._updateActions()
        return sess

    def _runQqueueInactive(self, op, name):
        """Execute qqueue operation after inactivating the specified queue"""
        assert self._repoagent
        if not self._cmdsession.isFinished():
            return cmdcore.nullCmdSession()

        if name != self._activeName():
            return self._runQqueue(op, name)

        sacrifices = [n for n in self._existingNames() if n != name]
        if not sacrifices:
            return self._runQqueue(op, name)  # will exit with error

        opts = {}
        if op:
            opts[op] = True
        cmdlines = [hglib.buildcmdargs('qqueue', sacrifices[0]),
                    hglib.buildcmdargs('qqueue', name, **opts)]
        self._cmdsession = sess = self._repoagent.runCommandSequence(cmdlines,
                                                                     self)
        sess.commandFinished.connect(self._onCommandFinished)
        self._updateActions()
        return sess

    @pyqtSlot(int)
    def _onCommandFinished(self, ret):
        if ret != 0:
            cmdui.errorMessageBox(self._cmdsession, self.parent())
        self._updateActions()


class PatchQueueActions(QObject):
    """Container for MQ patch actions except for queue management"""

    def __init__(self, parent=None):
        super(PatchQueueActions, self).__init__(parent)
        assert parent is None or isinstance(parent, QWidget)
        self._repoagent = None
        self._cmdsession = cmdcore.nullCmdSession()
        self._opts = {'force': False, 'keep_changes': False}

    def setRepoAgent(self, repoagent):
        self._repoagent = repoagent

    def gotoPatch(self, patch):
        opts = {'force': self._opts['force'],
                'keep_changes': self._opts['keep_changes']}
        return self._runCommand('qgoto', [patch], opts, self._onPushFinished)

    @pyqtSlot()
    def pushPatch(self, patch=None, move=False, exact=False):
        return self._runPush(patch, move=move, exact=exact)

    @pyqtSlot()
    def pushAllPatches(self):
        return self._runPush(None, all=True)

    def _runPush(self, patch, **opts):
        opts['force'] = self._opts['force']
        if not opts.get('exact'):
            # --exact and --keep-changes cannot be used simultaneously
            # thus we ignore the "default" setting for --keep-changes
            # when --exact is explicitly set
            opts['keep_changes'] = self._opts['keep_changes']
        return self._runCommand('qpush', [patch], opts, self._onPushFinished)

    @pyqtSlot()
    def popPatch(self, patch=None):
        return self._runPop(patch)

    @pyqtSlot()
    def popAllPatches(self):
        return self._runPop(None, all=True)

    def _runPop(self, patch, **opts):
        opts['force'] = self._opts['force']
        opts['keep_changes'] = self._opts['keep_changes']
        return self._runCommand('qpop', [patch], opts)

    def renamePatch(self, patch, newname):
        return self._runCommand('qrename', [patch, newname], {})

    def guardPatch(self, patch, guards):
        args = [patch]
        args.extend(guards)
        opts = {'none': not guards}
        return self._runCommand('qguard', args, opts)

    def selectGuards(self, guards):
        opts = {'none': not guards}
        return self._runCommand('qselect', guards, opts)

    def abort(self):
        self._cmdsession.abort()

    def _runCommand(self, name, args, opts, finishslot=None):
        assert self._repoagent
        if not self._cmdsession.isFinished():
            return cmdcore.nullCmdSession()
        cmdline = hglib.buildcmdargs(name, *args, **opts)
        self._cmdsession = sess = self._repoagent.runCommand(cmdline, self)
        sess.commandFinished.connect(finishslot or self._onCommandFinished)
        return sess

    @pyqtSlot(int)
    def _onPushFinished(self, ret):
        if ret != 0 and self._repoagent:
            repo = self._repoagent.rawRepo()
            output = hglib.fromunicode(self._cmdsession.warningString())
            if mqutil.checkForRejects(repo, output, self.parent()) > 0:
                ret = 0  # no further error dialog
        if ret != 0:
            cmdui.errorMessageBox(self._cmdsession, self.parent())

    @pyqtSlot(int)
    def _onCommandFinished(self, ret):
        if ret != 0:
            cmdui.errorMessageBox(self._cmdsession, self.parent())

    @pyqtSlot()
    def launchOptionsDialog(self):
        dlg = OptionsDialog(self._opts, self.parent())
        dlg.finished.connect(dlg.deleteLater)
        dlg.setWindowFlags(Qt.Sheet)
        dlg.setWindowModality(Qt.WindowModal)
        if dlg.exec_() == QDialog.Accepted:
            self._opts.update(dlg.outopts)


class MQPatchesWidget(QDockWidget):
    showMessage = pyqtSignal(unicode)
    patchSelected = pyqtSignal(unicode)

    def __init__(self, parent):
        QDockWidget.__init__(self, parent)
        self._repoagent = None

        self.setFeatures(QDockWidget.DockWidgetClosable |
                         QDockWidget.DockWidgetMovable  |
                         QDockWidget.DockWidgetFloatable)
        self.setWindowTitle(_('Patch Queue'))

        w = QWidget()
        mainlayout = QVBoxLayout()
        mainlayout.setContentsMargins(0, 0, 0, 0)
        w.setLayout(mainlayout)
        self.setWidget(w)

        self.patchActions = PatchQueueActions(self)

        # top toolbar
        w = QWidget()
        tbarhbox = QHBoxLayout()
        tbarhbox.setContentsMargins(0, 0, 0, 0)
        w.setLayout(tbarhbox)
        mainlayout.addWidget(w)

        # TODO: move QAction instances to PatchQueueActions
        self.qpushAllAct = a = QAction(
            geticon('hg-qpush-all'), _('Push all', 'MQ QPush'), self)
        a.setToolTip(_('Apply all patches'))
        self.qpushAct = a = QAction(
            geticon('hg-qpush'), _('Push', 'MQ QPush'), self)
        a.setToolTip(_('Apply one patch'))
        self.setGuardsAct = a = QAction(
            geticon('hg-qguard'), _('Guards'), self)
        a.setToolTip(_('Configure guards for selected patch'))
        self.qreorderAct = a = QAction(
            geticon('hg-qreorder'), _('Reorder patches'), self)
        a.setToolTip(_('Reorder patches'))
        self.qdeleteAct = a = QAction(
            geticon('hg-qdelete'), _('Delete'), self)
        a.setToolTip(_('Delete selected patches'))
        self.qpopAct = a = QAction(
            geticon('hg-qpop'), _('Pop'), self)
        a.setToolTip(_('Unapply one patch'))
        self.qpopAllAct = a = QAction(
            geticon('hg-qpop-all'), _('Pop all'), self)
        a.setToolTip(_('Unapply all patches'))
        self.qtbar = tbar = QToolBar(_('Patch Queue Actions Toolbar'))
        tbar.setIconSize(QSize(18, 18))
        tbarhbox.addWidget(tbar)
        tbar.addAction(self.qpushAct)
        tbar.addAction(self.qpushAllAct)
        tbar.addSeparator()
        tbar.addAction(self.qpopAct)
        tbar.addAction(self.qpopAllAct)
        tbar.addSeparator()
        tbar.addAction(self.qreorderAct)
        tbar.addSeparator()
        tbar.addAction(self.qdeleteAct)
        tbar.addSeparator()
        tbar.addAction(self.setGuardsAct)

        self.queueFrame = w = QFrame()
        mainlayout.addWidget(w)

        # Patch Queue Frame
        layout = QVBoxLayout()
        layout.setSpacing(5)
        layout.setContentsMargins(0, 0, 0, 0)
        self.queueFrame.setLayout(layout)

        qqueuehbox = QHBoxLayout()
        qqueuehbox.setSpacing(5)
        layout.addLayout(qqueuehbox)
        self.qqueueComboWidget = QComboBox(self)
        qqueuehbox.addWidget(self.qqueueComboWidget, 1)
        self.qqueueConfigBtn = QToolButton(self)
        self.qqueueConfigBtn.setText('...')
        self.qqueueConfigBtn.setPopupMode(QToolButton.InstantPopup)
        qqueuehbox.addWidget(self.qqueueConfigBtn)

        self.qqueueActions = QueueManagementActions(self)
        self.qqueueConfigBtn.setMenu(self.qqueueActions.createMenu(self))

        self.queueListWidget = QListWidget(self)
        self.queueListWidget.setIconSize(QSize(12, 12))
        layout.addWidget(self.queueListWidget, 1)

        bbarhbox = QHBoxLayout()
        bbarhbox.setSpacing(5)
        layout.addLayout(bbarhbox)
        self.guardSelBtn = QPushButton()
        menu = QMenu(self)
        menu.triggered.connect(self.onGuardSelectionChange)
        self.guardSelBtn.setMenu(menu)
        bbarhbox.addWidget(self.guardSelBtn)

        self.qqueueComboWidget.activated[QString].connect(
            self.onQQueueActivated)

        self.queueListWidget.currentRowChanged.connect(self.onPatchSelected)
        self.queueListWidget.itemActivated.connect(self.onGotoPatch)
        self.queueListWidget.itemChanged.connect(self.onRenamePatch)

        self.qpushAllAct.triggered.connect(self.patchActions.pushAllPatches)
        self.qpushAct.triggered.connect(self.patchActions.pushPatch)
        self.qreorderAct.triggered.connect(self.onQreorder)
        self.qpopAllAct.triggered.connect(self.patchActions.popAllPatches)
        self.qpopAct.triggered.connect(self.patchActions.popPatch)
        self.setGuardsAct.triggered.connect(self.onGuardConfigure)
        self.qdeleteAct.triggered.connect(self.onDelete)

        self.setAcceptDrops(True)

        self.layout().setContentsMargins(2, 2, 2, 2)

        QTimer.singleShot(0, self.reload)

    @property
    def repo(self):
        if self._repoagent:
            return self._repoagent.rawRepo()

    def setRepoAgent(self, repoagent):
        if self._repoagent:
            self._repoagent.repositoryChanged.disconnect(self.reload)
        self._repoagent = None
        if repoagent and 'mq' in repoagent.rawRepo().extensions():
            self._repoagent = repoagent
            self._repoagent.repositoryChanged.connect(self.reload)
        self.patchActions.setRepoAgent(repoagent)
        self.qqueueActions.setRepoAgent(repoagent)
        QTimer.singleShot(0, self.reload)

    @pyqtSlot()
    def showActiveQueue(self):
        combo = self.qqueueComboWidget
        q = hglib.tounicode(self.repo.thgactivemqname)
        index = combo.findText(q)
        combo.setCurrentIndex(index)

    @pyqtSlot()
    def onQreorder(self):
        if qreorder.checkGuardsOrComments(self.repo, self):
            dlg = qreorder.QReorderDialog(self._repoagent, self)
            dlg.exec_()

    @pyqtSlot()
    def onGuardConfigure(self):
        item = self.queueListWidget.currentItem()
        patch = hglib.tounicode(item._thgpatch)
        if item._thgguards:
            uguards = hglib.tounicode(' '.join(item._thgguards))
        else:
            uguards = ''
        new, ok = qtlib.getTextInput(self,
                      _('Configure guards'),
                      _('Input new guards for %s:') % patch,
                      text=uguards)
        if not ok or new == uguards:
            return
        self.patchActions.guardPatch(patch, unicode(new).split())

    @pyqtSlot()
    def onDelete(self):
        patch = hglib.tounicode(self.queueListWidget.currentItem()._thgpatch)
        dlg = qdelete.QDeleteDialog(self._repoagent, [patch], self)
        if dlg.exec_() == QDialog.Accepted:
            self.reload()

    #@pyqtSlot(QListWidgetItem)
    def onGotoPatch(self, item):
        'Patch has been activated (return), issue qgoto'
        self.patchActions.gotoPatch(hglib.tounicode(item._thgpatch))

    #@pyqtSlot(QListWidgetItem)
    def onRenamePatch(self, item):
        'Patch has been renamed, issue qrename'
        newpatchname = hglib.fromunicode(item.text())
        if newpatchname == item._thgpatch:
            return
        else:
            res = qrename.checkPatchname(self.repo.root,
                        self.repo.thgactivemqname, newpatchname, self)
            if not res:
                item.setText(item._thgpatch)
                return
        self.patchActions.renamePatch(hglib.tounicode(item._thgpatch),
                                      item.text())

    @pyqtSlot(int)
    def onPatchSelected(self, row):
        'Patch has been selected, update buttons'
        if row >= 0:
            patch = self.queueListWidget.item(row)._thgpatch
            applied = set([p.name for p in self.repo.mq.applied])
            self.qdeleteAct.setEnabled(patch not in applied)
            self.setGuardsAct.setEnabled(True)
            self.patchSelected.emit(hglib.tounicode(patch))
        else:
            self.qdeleteAct.setEnabled(False)
            self.setGuardsAct.setEnabled(False)

    @pyqtSlot(QString)
    def onQQueueActivated(self, text):
        if text == hglib.tounicode(self.repo.thgactivemqname):
            return

        if qtlib.QuestionMsgBox(_('Confirm patch queue switch'),
                _("Do you really want to activate patch queue '%s' ?") % text,
                parent=self, defaultbutton=QMessageBox.No):
            sess = self.qqueueActions.switchQueue(text)
            sess.commandFinished.connect(self.showActiveQueue)
        else:
            self.showActiveQueue()

    @pyqtSlot()
    def reload(self):
        try:
            self._reload()
        except Exception, e:
            self.showMessage.emit(hglib.tounicode(str(e)))
            if 'THGDEBUG' in os.environ:
                import traceback
                traceback.print_exc()

    def _reload(self):
        if self.repo is None:
            self.queueListWidget.clear()
            self.qqueueComboWidget.setEnabled(False)
            self.qqueueConfigBtn.setEnabled(False)
            self.guardSelBtn.setEnabled(False)
            self.qpushAllAct.setEnabled(False)
            self.qpushAct.setEnabled(False)
            self.qdeleteAct.setEnabled(False)
            self.setGuardsAct.setEnabled(False)
            self.qpopAct.setEnabled(False)
            self.qpopAllAct.setEnabled(False)
            self.qreorderAct.setEnabled(False)
            return

        self.loadQQueues()
        self.showActiveQueue()

        repo = self.repo

        applied = set([p.name for p in repo.mq.applied])
        self.allguards = set()
        items = []
        for idx, patch in enumerate(repo.mq.series):
            ctx = repo.changectx(patch)
            desc = ctx.longsummary()
            item = QListWidgetItem(hglib.tounicode(patch))
            if patch in applied: # applied
                f = item.font()
                f.setBold(True)
                item.setFont(f)
                item.setIcon(qtlib.geticon('hg-patch-applied'))
            else:
                pushable, why = repo.mq.pushable(idx)
                if not pushable: # guarded
                    f = item.font()
                    f.setItalic(True)
                    item.setFont(f)
                    item.setIcon(qtlib.geticon('hg-patch-guarded'))
                elif why is not None:
                    item.setIcon(qtlib.geticon('hg-patch-unguarded'))
            patchguards = repo.mq.seriesguards[idx]
            if patchguards:
                for guard in patchguards:
                    self.allguards.add(guard[1:])
                uguards = hglib.tounicode(', '.join(patchguards))
            else:
                uguards = _('no guards')
            uname = hglib.tounicode(patch)
            item._thgpatch = patch
            item._thgguards = patchguards
            item.setToolTip(u'%s: %s\n%s' % (uname, uguards, desc))
            item.setFlags(Qt.ItemIsSelectable |
                          Qt.ItemIsEditable |
                          Qt.ItemIsEnabled)
            items.append(item)

        item = self.queueListWidget.currentItem()
        if item:
            wasselected = item._thgpatch
        else:
            wasselected = None
        reselectPatchItem = None

        self.queueListWidget.blockSignals(True)
        self.queueListWidget.clear()
        for item in reversed(items):
            self.queueListWidget.addItem(item)
            if item._thgpatch == wasselected:
                reselectPatchItem = item
        self.queueListWidget.blockSignals(False)

        self.queueListWidget.setCurrentItem(reselectPatchItem)

        for guard in repo.mq.active():
            self.allguards.add(guard)
        self.refreshSelectedGuards()

        self.qqueueComboWidget.setEnabled(self.qqueueComboWidget.count() > 1)
        self.qqueueConfigBtn.setEnabled(True)
        self.qpushAllAct.setEnabled(bool(repo.thgmqunappliedpatches))
        self.qpushAct.setEnabled(bool(repo.thgmqunappliedpatches))
        self.qdeleteAct.setEnabled(False)
        self.setGuardsAct.setEnabled(False)
        self.qpopAct.setEnabled(bool(applied))
        self.qpopAllAct.setEnabled(bool(applied))
        self.qreorderAct.setEnabled(bool(repo.thgmqunappliedpatches))

    def loadQQueues(self):
        repo = self.repo
        combo = self.qqueueComboWidget
        combo.clear()
        combo.addItems(mqutil.getQQueues(repo))

    def refreshSelectedGuards(self):
        total = len(self.allguards)
        count = len(self.repo.mq.active())
        menu = self.guardSelBtn.menu()
        menu.clear()
        for guard in self.allguards:
            a = menu.addAction(hglib.tounicode(guard))
            a.setCheckable(True)
            a.setChecked(guard in self.repo.mq.active())
        self.guardSelBtn.setText(_('Guards: %d/%d') % (count, total))
        self.guardSelBtn.setEnabled(bool(total))

    @pyqtSlot(QAction)
    def onGuardSelectionChange(self, action):
        guard = hglib.fromunicode(action.text())
        newguards = self.repo.mq.active()[:]
        if action.isChecked():
            newguards.append(guard)
        elif guard in newguards:
            newguards.remove(guard)
        self.patchActions.selectGuards(map(hglib.tounicode, newguards))

    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Escape:
            self.patchActions.abort()
            self.qqueueActions.abort()
        else:
            return super(MQPatchesWidget, self).keyPressEvent(event)


class OptionsDialog(QDialog):
    'Utility dialog for configuring uncommon options'
    def __init__(self, opts, parent=None):
        QDialog.__init__(self, parent)
        self.setWindowTitle(_('MQ options'))

        layout = QVBoxLayout()
        self.setLayout(layout)

        self.forcecb = QCheckBox(
            _('Force push or pop (--force)'))
        layout.addWidget(self.forcecb)

        self.keepcb = QCheckBox(
            _('Tolerate non-conflicting local changes (--keep-changes)'))
        layout.addWidget(self.keepcb)

        self.forcecb.setChecked(opts.get('force', False))
        self.keepcb.setChecked(opts.get('keep_changes', False))

        for cb in [self.forcecb, self.keepcb]:
            cb.clicked.connect(self._resolveopts)

        BB = QDialogButtonBox
        bb = QDialogButtonBox(BB.Ok|BB.Cancel)
        bb.accepted.connect(self.accept)
        bb.rejected.connect(self.reject)
        self.bb = bb
        layout.addWidget(bb)

    #@pyqtSlot()
    def _resolveopts(self):
        # cannot use both --force and --keep-changes
        exclmap = {self.forcecb: [self.keepcb],
                   self.keepcb: [self.forcecb],
                   }
        sendercb = self.sender()
        if sendercb.isChecked():
            for cb in exclmap[sendercb]:
                cb.setChecked(False)

    def accept(self):
        outopts = {}
        outopts['force'] = self.forcecb.isChecked()
        outopts['keep_changes'] = self.keepcb.isChecked()
        self.outopts = outopts
        QDialog.accept(self)
