def onThreadFinished(self, ret): if self.stbar: error = False if ret is None: self.stbar.clear() if self.thread.abortbyuser: status = _('Terminated by user') else: status = _('Terminated') elif ret == 0: status = _('Finished') else: status = _('Failed!') error = True self.stbar.showMessage(status, error) self.display = None if ret == 0 and self.runNext(): return # run next command else: self.queue = [] text = self.thread.rawoutput.join('') self.rawoutlines = [hglib.fromunicode(text, 'replace')] self.commandFinished.emit(ret)
def linkActivated(self, cmd): if cmd == 'resolve': dlg = resolve.ResolveDialog(self._repoagent, self) dlg.exec_() self.checkResolve() elif cmd == 'commit': dlg = commit.CommitDialog(self._repoagent, [], {}, self) dlg.finished.connect(dlg.deleteLater) dlg.exec_() self.destcsinfo.update(self.repo['.']) self.checkStatus() elif cmd == 'discard': labels = [(QMessageBox.Yes, _('&Discard')), (QMessageBox.No, _('Cancel'))] if not qtlib.QuestionMsgBox(_('Confirm Discard'), _('Discard outstanding changes to working directory?'), labels=labels, parent=self): return def finished(ret): self.repo.decrementBusyCount() if ret == 0: self.checkStatus() cmdline = ['update', '--clean', '--repository', self.repo.root, '--rev', '.'] self.runner = cmdui.Runner(True, self) self.runner.commandFinished.connect(finished) self.repo.incrementBusyCount() self.runner.run(cmdline)
def launchtool(cmd, opts, replace, block): def quote(match): key = match.group()[1:] return util.shellquote(replace[key]) if isinstance(cmd, unicode): cmd = hglib.fromunicode(cmd) lopts = [] for opt in opts: if isinstance(opt, unicode): lopts.append(hglib.fromunicode(opt)) else: lopts.append(opt) args = ' '.join(lopts) args = re.sub(_regex, quote, args) cmdline = util.shellquote(cmd) + ' ' + args cmdline = util.quotecommand(cmdline) try: proc = subprocess.Popen(cmdline, shell=True, creationflags=qtlib.openflags, stderr=subprocess.PIPE, stdout=subprocess.PIPE, stdin=subprocess.PIPE) if block: proc.communicate() except (OSError, EnvironmentError), e: QMessageBox.warning(None, _('Tool launch failure'), _('%s : %s') % (cmd, str(e)))
def _showexceptiondialog(self): from tortoisehg.hgqt.bugreport import BugReport, ExceptionMsgBox opts = {} opts['cmd'] = ' '.join(sys.argv[1:]) opts['error'] = ''.join(''.join(traceback.format_exception(*args)) for args in self.errors) etype, evalue = self.errors[0][:2] if len(self.errors) == 1 and etype in self._recoverableexc: opts['values'] = evalue errstr = self._recoverableexc[etype] if etype == error.Abort and evalue.hint: errstr = u''.join([errstr, u'<br><b>', _('hint:'), u'</b> %(arg1)s']) opts['values'] = [str(evalue), evalue.hint] dlg = ExceptionMsgBox(hglib.tounicode(str(evalue)), hglib.tounicode(errstr), opts, parent=self._mainapp.activeWindow()) elif etype is KeyboardInterrupt: if qtlib.QuestionMsgBox(_('Keyboard interrupt'), _('Close this application?')): QApplication.quit() else: self.errors = [] return else: dlg = BugReport(opts, parent=self._mainapp.activeWindow()) dlg.exec_()
def __init__(self, repo, patches, parent): super(QDeleteDialog, self).__init__(parent) self.setWindowTitle(_('Patch remove - %s') % repo.displayname) self.setWindowIcon(qtlib.geticon('hg-qdelete')) f = self.windowFlags() self.setWindowFlags(f & ~Qt.WindowContextHelpButtonHint) self.repo = repo self.patches = patches self.setLayout(QVBoxLayout()) msg = _('Remove patches from queue?') patchesu = u'<li>'.join([hglib.tounicode(p) for p in patches]) lbl = QLabel(u'<b>%s<ul><li>%s</ul></b>' % (msg, patchesu)) self.layout().addWidget(lbl) self.keepchk = QCheckBox(_('Keep patch files')) self.keepchk.setChecked(True) self.layout().addWidget(self.keepchk) self.cmd = cmdui.Runner(False, self) self.cmd.output.connect(self.output) self.cmd.makeLogVisible.connect(self.makeLogVisible) BB = QDialogButtonBox bbox = QDialogButtonBox(BB.Ok|BB.Cancel) bbox.accepted.connect(self.accept) bbox.rejected.connect(self.reject) self.layout().addWidget(bbox) self.bbox = bbox
def findRenames(self): 'User pressed "find renames" button' if self.thread and self.thread.isRunning(): QMessageBox.information(self, _('Search already in progress'), _('Cannot start a new search')) return ulist = [it.orig for it in self.unrevlist.selectedItems()] if not ulist: # When no files are selected, look for all files ulist = [self.unrevlist.item(n).orig for n in range(self.unrevlist.count())] if not ulist: QMessageBox.information(self, _('No files to find'), _('There are no files that may have been renamed')) return pct = self.simslider.value() / 100.0 copies = not self.copycheck.isChecked() self.findbtn.setEnabled(False) self.matchtv.model().clear() self.thread = RenameSearchThread(self.repo, ulist, pct, copies) self.thread.match.connect(self.rowReceived) self.thread.progress.connect(self.stbar.progress) self.thread.showMessage.connect(self.stbar.showMessage) self.thread.finished.connect(self.searchfinished) self.thread.start()
def checkPatchname(reporoot, activequeue, newpatchname, parent): if activequeue == 'patches': pn = 'patches' else: pn = 'patches-%s' % activequeue patchfile = os.sep.join([reporoot, ".hg", pn, newpatchname]) if os.path.exists(patchfile): dlg = CheckPatchnameDialog(newpatchname, parent) choice = dlg.exec_() if choice == 1: # add .OLD to existing patchfile try: os.rename(patchfile, patchfile + '.OLD') except (OSError, IOError), inst: qtlib.ErrorMsgBox(self.errTitle, _('Could not rename existing patchfile'), hglib.tounicode(str(inst))) return False return True elif choice == 2: # overwite existing patchfile try: os.remove(patchfile) except (OSError, IOError), inst: qtlib.ErrorMsgBox(self.errTitle, _('Could not delete existing patchfile'), hglib.tounicode(str(inst))) return False return True
def __init__(self, repo, patchname, parent): super(QRenameDialog, self).__init__(parent) self.setWindowTitle(_('Patch rename - %s') % repo.displayname) f = self.windowFlags() self.setWindowFlags(f & ~Qt.WindowContextHelpButtonHint) self.setMinimumWidth(400) self.repo = repo self.oldpatchname = patchname self.newpatchname = '' self.setLayout(QVBoxLayout()) lbl = QLabel(_('Rename patch <b>%s</b> to:') % hglib.tounicode(self.oldpatchname)) self.layout().addWidget(lbl) self.le = QLineEdit(hglib.tounicode(self.oldpatchname)) self.layout().addWidget(self.le) self.cmd = cmdui.Runner(True, self) self.cmd.output.connect(self.output) self.cmd.makeLogVisible.connect(self.makeLogVisible) self.cmd.commandFinished.connect(self.onCommandFinished) BB = QDialogButtonBox bbox = QDialogButtonBox(BB.Ok|BB.Cancel) bbox.accepted.connect(self.accept) bbox.rejected.connect(self.reject) self.layout().addWidget(bbox) self.bbox = bbox self.focus = self.le
def acceptMatch(self): 'User pressed "accept match" button' remdests = {} wctx = self.repo[None] m = self.matchtv.model() # If no rows are selected, ask the user if he'd like to accept all renames if self.matchtv.selectionModel().hasSelection(): itemList = [self.matchtv.model().getRow(index) \ for index in self.matchtv.selectionModel().selectedRows()] else: itemList = m.rows for item in itemList: src, dest, percent = item if dest in remdests: udest = hglib.tounicode(dest) QMessageBox.warning(self, _('Multiple sources chosen'), _('You have multiple renames selected for ' 'destination file:\n%s. Aborting!') % udest) return remdests[dest] = src for dest, src in remdests.iteritems(): if not os.path.exists(self.repo.wjoin(src)): wctx.forget([src]) # !->R wctx.copy(src, dest) self.matchtv.model().remove(dest) self.matchAccepted.emit() self.refresh()
def _updateSourceTitle(self, idx): numrevs = len(self.sourcelist) if numrevs <= 1: title = _('Graft changeset') else: title = _('Graft changeset #%d of %d') % (idx + 1, numrevs) self.srcb.setTitle(title)
def refreshWctx(self, synchronous=False): if self.refthread: return self.fileview.clearDisplay() # store selected paths or current path model = self.tv.model() if model and model.rowCount(QModelIndex()): smodel = self.tv.selectionModel() curidx = smodel.currentIndex() if curidx.isValid(): curpath = model.getRow(curidx)[COL_PATH] else: curpath = None spaths = [model.getRow(i)[COL_PATH] for i in smodel.selectedRows()] self.reselection = spaths, curpath else: self.reselection = None if self.checkable: self.checkAllNoneBtn.setEnabled(False) self.refreshBtn.setEnabled(False) self.progress.emit(*cmdui.startProgress(_('Refresh'), _('status'))) self.refthread = StatusThread(self.repo, self.pctx, self.pats, self.opts) if not synchronous: self.refthread.finished.connect(self.reloadComplete) self.refthread.showMessage.connect(self.showMessage) self.refthread.start() if synchronous: self.reloadComplete()
def _initbranchfilter(self): self._branchLabel = QToolButton( text=_('Branch'), popupMode=QToolButton.MenuButtonPopup, statusTip=_('Display graph the named branch only')) self._branchLabel.clicked.connect(self._branchLabel.showMenu) self._branchMenu = QMenu(self._branchLabel) self._abranchAction = self._branchMenu.addAction( _('Display only active branches'), self.refresh) self._abranchAction.setCheckable(True) self._cbranchAction = self._branchMenu.addAction( _('Display closed branches'), self.refresh) self._cbranchAction.setCheckable(True) self._allparAction = self._branchMenu.addAction( _('Include all ancestors'), self._emitBranchChanged) self._allparAction.setCheckable(True) self._branchLabel.setMenu(self._branchMenu) self._branchCombo = QComboBox() self._branchCombo.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) self._branchCombo.setSizeAdjustPolicy(QComboBox.AdjustToMinimumContentsLength) self._branchCombo.currentIndexChanged.connect(self._emitBranchChanged) self._branchReloading = False self.addWidget(self._branchLabel) self.addWidget(qtlib.Spacer(2, 2)) self.addWidget(self._branchCombo)
def nomarkup(widget, item, value): def revline_markup(revnum, revid, summary, highlight=None, branch=None): summary = qtlib.markup(summary) if revid: rev = revid_markup('%s (%s)' % (revnum, revid)) return '%s %s' % (rev, summary) else: revnum = qtlib.markup(revnum) return '%s - %s' % (revnum, summary) csets = [] if item == 'ishead': if value is False: text = _('Not a head revision!') return qtlib.markup(text, fg='red', weight='bold') raise csinfo.UnknownItem(item) elif item == 'isclose': if value is True: text = _('Head is closed!') return qtlib.markup(text, fg='red', weight='bold') raise csinfo.UnknownItem(item) for cset in value: if isinstance(cset, basestring): csets.append(revid_markup(cset)) else: csets.append(revline_markup(*cset)) return csets
def show_patch_cmenu(self, pos): """Context menu for selected patch""" patchname = self.selected_patch() if not patchname: return menu = QMenu(self) def append(label, handler): menu.addAction(label).triggered.connect(handler) has_pbranch = self.has_pbranch() is_current = self.has_patch() and self.cur_branch() == patchname is_patch = self.is_patch(patchname) is_internal = self.pbranch.isinternal(patchname) is_merge = len(self.repo.branchheads(patchname)) > 1 #if has_pbranch and not is_merge and not is_internal: # append(_('&New'), self.pnew_activated) if not is_current: append(_('&Goto (update workdir)'), self.goto_activated) if is_patch: append(_('&Merge'), self.merge_activated) # append(_('&Edit message'), self.edit_message_activated) # append(_('&Rename'), self.rename_activated) # append(_('&Delete'), self.delete_activated) # append(_('&Finish'), self.finish_activated) if len(menu.actions()) > 0: menu.exec_(pos)
def edit_pgraph_clicked(self): opts = {} # TODO: How to find user ID mgr = self.pbranch.patchmanager(self.repo.ui, self.repo, opts) if not mgr.hasgraphdesc(): self.pbranch.writefile(mgr.graphdescpath(), '') oldtext = mgr.graphdesc() # run editor in the repository root olddir = os.getcwd() os.chdir(self.repo.root) try: newtext = None newtext = self.repo.ui.edit(oldtext, opts.get('user')) except error.Abort: no_editor_configured =(os.environ.get("HGEDITOR") or self.repo.ui.config("ui", "editor") or os.environ.get("VISUAL") or os.environ.get("EDITOR","editor-not-configured") == "editor-not-configured") if no_editor_configured: qtlib.ErrorMsgBox(_('No editor found'), _('Mercurial was unable to find an editor. Please configure Mercurial to use an editor installed on your system.')) else: raise os.chdir(olddir) if newtext is not None: mgr.updategraphdesc(newtext) self.refresh()
def removeFile(self, wfile): repo = self.repo ctx = self.ctx if isinstance(ctx, patchctx): repo.thgbackup(ctx._path) fp = util.atomictempfile(ctx._path, 'wb') try: if ctx._ph.comments: fp.write('\n'.join(ctx._ph.comments)) fp.write('\n\n') for file in ctx._fileorder: if file == wfile: continue for chunk in ctx._files[file]: chunk.write(fp) fp.close() finally: del fp ctx.invalidate() else: fullpath = repo.wjoin(wfile) repo.thgbackup(fullpath) wasadded = wfile in repo[None].added() try: commands.revert(repo.ui, repo, fullpath, rev='.', no_backup=True) if wasadded and os.path.exists(fullpath): os.unlink(fullpath) except EnvironmentError: qtlib.InfoMsgBox(_("Unable to remove"), _("Unable to remove file %s,\n" "permission denied") % hglib.tounicode(wfile)) self.fileModified.emit()
def pstatus(self, patch_name): """ [pbranch] Execute 'pstatus' command. :param patch_name: Name of patch-branch :retv: list of status messages. If empty there is no pending merges """ if self.pbranch is None: return None status = [] opts = {} mgr = self.pbranch.patchmanager(self.repo.ui, self.repo, opts) graph = mgr.graphforopts(opts) graph_cur = mgr.graphforopts({'tips': True}) heads = self.repo.branchheads(patch_name) if graph_cur.isinner(patch_name) and not graph.isinner(patch_name): status.append(_('will be closed')) if len(heads) > 1: status.append(_('needs merge of %i heads\n') % len(heads)) for dep, through in graph.pendingmerges(patch_name): if through: status.append(_('needs merge with %s (through %s)\n') % (dep, ", ".join(through))) else: status.append(_('needs merge with %s\n') % dep) for dep in graph.pendingrebases(patch_name): status.append(_('needs update of diff base to tip of %s\n') % dep) return status
def newShelf(self, interactive): shelve = time.strftime('%Y-%m-%d_%H-%M-%S') + \ '_parent_rev_%d' % self.repo['.'].rev() if interactive: dlg = QInputDialog(self, Qt.Sheet) dlg.setWindowModality(Qt.WindowModal) dlg.setWindowTitle(_('TortoiseHg New Shelf Name')) dlg.setLabelText(_('Specify name of new shelf')) dlg.setTextValue(shelve) if not dlg.exec_(): return shelve = hglib.fromunicode(dlg.textValue()) try: fn = os.path.join('shelves', shelve) shelfpath = self.repo.join(fn) if os.path.exists(shelfpath): qtlib.ErrorMsgBox(_('File already exists'), _('A shelf file of that name already exists')) return self.repo.makeshelf(shelve) self.showMessage(_('New shelf created')) self.refreshCombos() if shelfpath in self.shelves: self.combob.setCurrentIndex(self.shelves.index(shelfpath)) except EnvironmentError, e: self.showMessage(hglib.tounicode(str(e)))
def handleerror(error): msgmap = {QProcess.FailedToStart: _("failed to run command\n"), QProcess.Crashed: _("crashed\n")} if extproc.state() == QProcess.NotRunning: self._logwidget.closePrompt() self._logwidget.appendLog(msgmap.get(error, _("error while running command\n")), "ui.error") if extproc.state() == QProcess.NotRunning: self._logwidget.openPrompt()
def mqNewRefreshCommand(repo, isnew, stwidget, pnwidget, message, opts, olist): if isnew: name = hglib.fromunicode(pnwidget.text()) if not name: qtlib.ErrorMsgBox(_('Patch Name Required'), _('You must enter a patch name')) pnwidget.setFocus() return cmdline = ['qnew', '--repository', repo.root, name] else: cmdline = ['qrefresh', '--repository', repo.root] if message: cmdline += ['--message=' + hglib.fromunicode(message)] cmdline += getUserOptions(opts, *olist) files = ['--'] + [repo.wjoin(x) for x in stwidget.getChecked()] addrem = [repo.wjoin(x) for x in stwidget.getChecked('!?')] if len(files) > 1: cmdline += files else: cmdline += ['--exclude', repo.root] if addrem: cmdlines = [ ['addremove', '-R', repo.root] + addrem, cmdline] else: cmdlines = [cmdline] return cmdlines
def interact_handler(self, wrapper): prompt, password, choices, default = wrapper.data prompt = hglib.tounicode(prompt) if choices: dlg = QMessageBox(QMessageBox.Question, _('TortoiseHg Prompt'), prompt, parent=self.parent()) dlg.setWindowFlags(Qt.Sheet) dlg.setWindowModality(Qt.WindowModal) for index, choice in enumerate(choices): button = dlg.addButton(hglib.tounicode(choice), QMessageBox.ActionRole) button.response = index if index == default: dlg.setDefaultButton(button) dlg.exec_() button = dlg.clickedButton() if button is 0: self.responseq.put(None) else: self.responseq.put(button.response) else: mode = password and QLineEdit.Password \ or QLineEdit.Normal text, ok = qtlib.getTextInput(self.parent(), _('TortoiseHg Prompt'), prompt.title(), mode=mode) if ok: text = hglib.fromunicode(text) else: text = None self.responseq.put(text)
def checkResolve(self): for root, path, status in thgrepo.recursiveMergeStatus(self.repo): if status == 'u': txt = _('Graft generated merge <b>conflicts</b> that must ' 'be <a href="resolve"><b>resolved</b></a>') self.graftbtn.setEnabled(False) break else: self.graftbtn.setEnabled(True) txt = _('You may continue the graft') self.showMessage.emit(txt) currgraftrevs = self.graftstate() if currgraftrevs: def findrev(rev, revlist): rev = self.repo[rev].rev() for n, r in enumerate(revlist): r = self.repo[r].rev() if rev == r: return n return None idx = findrev(currgraftrevs[0], self.sourcelist) if idx is not None: self._updateSource(idx) self.abortbtn.setEnabled(True) self.graftbtn.setText('Continue') return True else: self.abortbtn.setEnabled(False) return False
def run(self): msg = None if not self.dialog.server: msg = _("Invalid Settings - The ReviewBoard server is not setup") elif not self.dialog.user: msg = _("Invalid Settings - Please provide your ReviewBoard username") else: rb = extensions.find("reviewboard") try: pwd = self.dialog.password #if we don't have a password send something here to skip #the cli getpass in the extension. We will set the password #later if not pwd: pwd = "None" self.reviewboard = rb.make_rbclient(self.dialog.server, self.dialog.user, pwd) self.loadCombos() except rb.ReviewBoardError, e: msg = e.msg except TypeError: msg = _("Invalid reviewboard plugin. Please download the " "mercurial reviewboard plugin version 3.5 or higher " "from the website below.\n\n %s") % \ u'http://bitbucket.org/mdelagra/mercurial-reviewboard/'
def savefile(self): filenames = self.filelist.getSelectedFiles() if not filenames: return rev = self.ctx.rev() for curfile in filenames: wfile = util.localpath(curfile) wfile, ext = os.path.splitext(os.path.basename(wfile)) if wfile: filename = "%s@%d%s" % (wfile, rev, ext) else: filename = "%s@%d" % (ext, rev) result = QFileDialog.getSaveFileName(parent=self, caption=_("Save file to"), directory=filename) if not result: continue cwd = os.getcwd() try: os.chdir(self.repo.root) try: commands.cat(self.repo.ui, self.repo, curfile, rev = rev, output = hglib.fromunicode(result)) except (util.Abort, IOError), e: QMessageBox.critical(self, _('Unable to save file'), hglib.tounicode(str(e))) finally: os.chdir(cwd)
def menuRequest(self, point): 'context menu request for unknown list' point = self.unknownlist.viewport().mapToGlobal(point) selected = [self.lclunknowns[i.row()] for i in sorted(self.unknownlist.selectedIndexes())] if len(selected) == 0: return if not self.contextmenu: self.contextmenu = QMenu(self) self.contextmenu.setTitle(_('Add ignore filter...')) else: self.contextmenu.clear() filters = [] if len(selected) == 1: local = selected[0] filters.append([local]) dirname = os.path.dirname(local) while dirname: filters.append([dirname]) dirname = os.path.dirname(dirname) base, ext = os.path.splitext(local) if ext: filters.append(['*'+ext]) filters.append(['**'+ext]) else: filters.append(selected) for f in filters: n = len(f) == 1 and f[0] or _('selected files') a = self.contextmenu.addAction(_('Ignore ') + hglib.tounicode(n)) a._patterns = f a.triggered.connect(self.insertFilters) self.contextmenu.exec_(point)
def accept(self): # If the editor has been modified, we implicitly accept the changes acceptresolution = self.editor.isModified() if not acceptresolution: action = QMessageBox.warning(self, _("Warning"), _("You have marked all rejected patch chunks as resolved yet you " \ "have not modified the file on the edit panel.\n\n" \ "This probably means that no code from any of the rejected patch " \ "chunks made it into the file.\n\n"\ "Are you sure that you want to leave the file as is and " \ "consider all the rejected patch chunks as resolved?\n\n" \ "Doing so may delete them from a shelve, for example, which " \ "would mean that you would lose them forever!\n\n" "Click Yes to accept the file as is or No to continue resolving " \ "the rejected patch chunks."), QMessageBox.Yes, QMessageBox.No) if action == QMessageBox.Yes: acceptresolution = True if acceptresolution: f = QFile(hglib.tounicode(self.path)) saved = f.open(QIODevice.WriteOnly) and self.editor.write(f) if not saved: qtlib.ErrorMsgBox(_('Unable to save file'), f.errorString(), parent=self) return self.saveSettings() super(RejectsDialog, self).accept()
def run(ui, *pats, **opts): repo = thgrepo.repository(None, paths.find_root()) if hasattr(repo, 'mq'): return QQueueDialog(repo) else: qtlib.ErrorMsgBox(_('TortoiseHg Error'), _('Please enable the MQ extension first.'))
def getCurrentUsername(widget, repo, opts=None): if opts: # 1. Override has highest priority user = opts.get('user') if user: return user # 2. Read from repository try: return repo.ui.username() except error.Abort: pass # 3. Get a username from the user QMessageBox.information(widget, _('Please enter a username'), _('You must identify yourself to Mercurial'), QMessageBox.Ok) from tortoisehg.hgqt.settings import SettingsDialog dlg = SettingsDialog(False, focus='ui.username') dlg.exec_() repo.invalidateui() try: return repo.ui.username() except error.Abort: return None
def validatePage(self): if self.cmd.core.running(): return False if len(self.repo.parents()) == 1: # commit succeeded, repositoryChanged() called wizard().next() if self.skiplast.isChecked(): self.wizard().close() return True user = qtlib.getCurrentUsername(self, self.repo) if not user: return False self.setTitle(_('Committing...')) self.setSubTitle(_('Please wait while committing merged files.')) message = hglib.fromunicode(self.msgEntry.text()) cmdline = ['commit', '--verbose', '--message', message, '--repository', self.repo.root, '--user', user] commandlines = [cmdline] pushafter = self.repo.ui.config('tortoisehg', 'cipushafter') if pushafter: cmd = ['push', '--repository', self.repo.root, pushafter] commandlines.append(cmd) self.repo.incrementBusyCount() self.cmd.setShowOutput(True) self.cmd.run(*commandlines) return False
def _initAnnotateOptionActions(self): self._annoptactions = [] for name, field in [(_("Show Author"), "author"), (_("Show Date"), "date"), (_("Show Revision"), "rev")]: a = QAction(name, self, checkable=True) a.setData(field) a.triggered.connect(self._updateAnnotateOption) self._annoptactions.append(a)
def uFinished(self): newver = (0, 0, 0) try: f = self._newverreply.readAll().data().splitlines() self._newverreply.close() self._newverreply = None newver = tuple([int(p) for p in f[0].split('.')]) upgradeurl = f[1] # generic download URL platform = sys.platform if platform == 'win32': from win32process import IsWow64Process as IsX64 platform = IsX64() and 'x64' or 'x86' # linux2 for Linux, darwin for OSX for line in f[2:]: p, _url = line.split(':', 1) if platform == p: upgradeurl = _url.strip() break except (IndexError, ImportError, ValueError): pass try: thgv = version.version() if '+' in thgv: thgv = thgv[:thgv.index('+')] curver = tuple([int(p) for p in thgv.split('.')]) except ValueError: curver = (0, 0, 0) if newver > curver: url_lbl = _('A new version of TortoiseHg is ready for download!') urldata = ('<a href=%s>%s</a>' % (upgradeurl, url_lbl)) self.download_url_lbl.setText(urldata)
def getVersionInfo(self): def make_version(tuple): vers = ".".join([str(x) for x in tuple]) return vers thgv = (_('version %s') % version.version()) libv = (_('with Mercurial-%s, Python-%s, PyQt-%s, Qt-%s') % \ (hglib.hgversion, make_version(sys.version_info[0:3]), PYQT_VERSION_STR, QT_VERSION_STR)) par = ('<p style=\" margin-top:0px; margin-bottom:6px;\">' '<span style=\"font-size:%spt; font-weight:600;\">' '%s</span></p>') name = (par % (14, 'TortoiseHg')) thgv = (par % (10, thgv)) nvl = ''.join([name, thgv, libv]) self.name_version_libs_lbl.setText(nvl)
def _get_bugtraq_object(self): if self.bugtr == None: obj = CreateObject(self.guid) try: self.bugtr = obj.QueryInterface(IBugTraqProvider2) except COMError: if not self.errorshown: self.errorshown = True qtlib.ErrorMsgBox( _('Issue Tracker Plugin Error'), _('Could not instantiate Issue Tracker plugin COM object' ), _('This error will not be shown again until you restart the workbench' )) return None return self.bugtr
def setupUi(self, o): self.editToolbar = QToolBar(self) self.editToolbar.setContextMenuPolicy(Qt.PreventContextMenu) self.addToolBar(Qt.ToolBarArea(Qt.TopToolBarArea), self.editToolbar) self.actionClose = QAction(self) self.actionClose.setShortcuts(QKeySequence.Close) self.actionReload = QAction(self) self.actionReload.setShortcuts(QKeySequence.Refresh) self.editToolbar.addAction(self.actionReload) self.addAction(self.actionClose) def layouttowidget(layout): w = QWidget() w.setLayout(layout) return w self.splitter = QSplitter(Qt.Vertical) self.setCentralWidget(self.splitter) self.horizontalLayout = QHBoxLayout() cs = ('fileDiffDialogLeft', _('File Differences Log Columns')) self.tableView_revisions_left = repoview.HgRepoView(self.repo, cs[0], cs, self) self.tableView_revisions_right = repoview.HgRepoView(self.repo, 'fileDiffDialogRight', cs, self) self.horizontalLayout.addWidget(self.tableView_revisions_left) self.horizontalLayout.addWidget(self.tableView_revisions_right) self.tableView_revisions_right.setSelectionMode(QAbstractItemView.SingleSelection) self.tableView_revisions_left.setSelectionMode(QAbstractItemView.SingleSelection) self.frame = QFrame() self.splitter.addWidget(layouttowidget(self.horizontalLayout)) self.splitter.addWidget(self.frame)
def qqueue(ui, repoagent, *pats, **opts): """manage multiple MQ patch queues""" from tortoisehg.hgqt import qqueue as qqueuemod repo = repoagent.rawRepo() if not hasattr(repo, 'mq'): raise util.Abort(_('Please enable the MQ extension first.')) return qqueuemod.QQueueDialog(repoagent)
def getVdiffFiles(self, tree): paths = self.getSelectedPaths(self.rtree) if not paths: return [] files, sub = [], False for root, wfile in paths: if root == self.repo.root: files.append(wfile) else: sub = True if sub: qtlib.InfoMsgBox( _('Unable to show subrepository files'), _('Visual diffs are not supported for files in ' 'subrepositories. They will not be shown.')) return files
def accept(self): # TODO: want to pass patchbombopts directly def cmdargs(opts): args = [] for k, v in opts.iteritems(): if isinstance(v, bool): if v: args.append('--%s' % k.replace('_', '-')) else: for e in isinstance(v, basestring) and [v] or v: args += ['--%s' % k.replace('_', '-'), e] return args hglib.loadextension(self._ui, 'patchbomb') opts = self._patchbombopts() try: cmd = cmdui.Dialog(['email'] + cmdargs(opts), parent=self) cmd.setWindowTitle(_('Sending Email')) cmd.setShowOutput(False) cmd.finished.connect(cmd.deleteLater) if cmd.exec_(): self._writehistory() finally: if 'desc' in opts: os.unlink(opts['desc']) # TODO: don't use tempfile
def qreorder(ui, repoagent, *pats, **opts): """Reorder unapplied MQ patches""" from tortoisehg.hgqt import qreorder as qreordermod repo = repoagent.rawRepo() if not hasattr(repo, 'mq'): raise util.Abort(_('Please enable the MQ extension first.')) return qreordermod.QReorderDialog(repoagent)
def _checkValidSelection(self): selection = self.repoview.selectedRevisions() if len(selection) > 2: msg = _('Too many rows selected for menu') else: msg = '' self.textView.showMessage.emit(msg)
def addglobalopts(aliases): if ui.verbose: option_lists.append((_("global options:"), globalopts)) if name == 'shortlist': option_lists.append((_('use "thg help" for the full list ' 'of commands'), ())) else: if name == 'shortlist': msg = _('use "thg help" for the full list of commands ' 'or "thg -v" for details') elif aliases: msg = _('use "thg -v help%s" to show aliases and ' 'global options') % (name and " " + name or "") else: msg = _('use "thg -v help %s" to show global options') % name option_lists.append((msg, ()))
def data(self, index, role): if not index.isValid(): return QVariant() path, status, mst, upath, ext, sz = self.rows[index.row()] if index.column() == COL_PATH: if role == Qt.CheckStateRole and self.checkable: # also Qt.PartiallyChecked if self.checked[path]: return Qt.Checked else: return Qt.Unchecked elif role == Qt.DisplayRole: return QVariant("") elif role == Qt.ToolTipRole: return QVariant(_('Checked count: %d') % self.checkCount) elif role == Qt.DisplayRole: return QVariant(self.rows[index.row()][index.column()]) elif role == Qt.TextColorRole: if mst: return _colors.get(mst.lower(), QColor('black')) else: return _colors.get(status, QColor('black')) elif role == Qt.ToolTipRole: return QVariant(statusMessage(status, mst, upath)) ''' elif role == Qt.DecorationRole and index.column() == COL_STATUS: if status in statusTypes: ico = QIcon() ico.addPixmap(QPixmap('icons/' + statusTypes[status].icon)) return QVariant(ico) ''' return QVariant()
def onCommandStarted(self): if self.stbar: self.stbar.showMessage(_('Running...')) self.commandStarted.emit() cmd = '%% hg %s\n' % self.display self.output.emit(hglib.tounicode(cmd), 'control')
def __init__(self, parent, alias, url_): super(PathEditDialog, self).__init__(parent) self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint) layout = QVBoxLayout() self.setLayout(layout) self.setWindowTitle(_("Edit Repository URL")) form = QFormLayout() layout.addLayout(form) form.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow) self.edit = QLineEdit(url_) form.addRow(alias, self.edit) BB = QDialogButtonBox bb = QDialogButtonBox(BB.Ok | BB.Cancel) layout.addWidget(bb) bb.accepted.connect(self.accept) bb.rejected.connect(self.reject) bb.button(BB.Ok).setDefault(True) self.setMinimumWidth(400) h = self.sizeHint().height() + 6 self.setMaximumHeight(h) self.setMinimumHeight(h)
def cmdFinished(ret): if ret != 0: lbl.setText(_('Error encountered.')) return repo.dirstate.invalidate() ctx = repo['.'] if ctx.rev() == self.lastrev: lbl.setText(_('Culprit found.')) return self.lastrev = ctx.rev() for b in self.nextbuttons: b.setEnabled(True) lbl.setText('%s: %d (%s) -> %s' % (_('Revision'), ctx.rev(), ctx, _('Test this revision and report findings. ' '(good/bad/skip)')))
def src_btn_clicked(self): """Select the source file of folder""" FD = QFileDialog curr = self.get_src() if os.path.isfile(curr): caption = _('Select Source File') path = FD.getOpenFileName(parent=self, caption=caption, options=FD.ReadOnly) else: caption = _('Select Source Folder') path = FD.getExistingDirectory(parent=self, caption=caption, options=FD.ShowDirsOnly | FD.ReadOnly) relpath = self.to_relative_path(path) if not relpath: return self.src_txt.setText(relpath)
def __init__(self, repoagent, otherrev, parent=None): super(MergeDialog, self).__init__(parent) f = self.windowFlags() self.setWindowFlags(f & ~Qt.WindowContextHelpButtonHint) repo = repoagent.rawRepo() self.otherrev = str(otherrev) self.localrev = str(repo['.'].rev()) self.setWindowTitle(_('Merge - %s') % repo.displayname) self.setWindowIcon(qtlib.geticon('hg-merge')) self.setOption(QWizard.NoBackButtonOnStartPage, True) self.setOption(QWizard.NoBackButtonOnLastPage, True) self.setOption(QWizard.IndependentPages, True) # set pages summarypage = SummaryPage(repoagent, self) self.addPage(summarypage) self.addPage(MergePage(repoagent, self)) self.addPage(CommitPage(repoagent, self)) self.addPage(ResultPage(repoagent, self)) self.currentIdChanged.connect(self.pageChanged) # move focus to "Next" button so that "Cancel" doesn't eat Enter key summarypage.refreshFinished.connect( self.button(QWizard.NextButton).setFocus) self.resize(QSize(700, 489).expandedTo(self.minimumSizeHint())) repoagent.repositoryChanged.connect(self.repositoryChanged) repoagent.configChanged.connect(self.configChanged)
def accept(self): if not self.isValid(): return if not self.password and not self.passwordPrompt(): return self.qui.progress_bar.show() self.qui.progress_label.setText("Posting Review...") self.qui.progress_label.show() def cmdargs(opts): args = [] for k, v in opts.iteritems(): if isinstance(v, bool): if v: args.append('--%s' % k.replace('_', '-')) else: for e in isinstance(v, basestring) and [v] or v: args += ['--%s' % k.replace('_', '-'), e] return args hglib.loadextension(self.ui, 'reviewboard') opts = self.postReviewOpts() revstr = str(self.selectedRevs.pop()) self.qui.post_review_button.setEnabled(False) self.qui.close_button.setEnabled(False) self.cmd = cmdui.Runner(False, self) self.cmd.setTitle(_('Review Board')) self.cmd.commandFinished.connect(self.onCompletion) self.cmd.run(['postreview'] + cmdargs(opts) + [revstr])
def menulist(self): acts = ['open', 'clone', 'addsubrepo', None, 'explore', 'terminal', 'copypath', None, 'rename', 'remove'] if self.childCount() > 0: acts.extend([None, (_('Sort'), ['sortbyname', 'sortbyhgsub'])]) acts.extend([None, 'settings']) return acts
def forceDisplayFile(self): if self.changes is not None: return self.sci.setText(_('Please wait while the file is opened ...')) # Wait a little to ensure that the "wait message" is displayed QTimer.singleShot(10, lambda: self.displayFile(self._filename, self._status, force=True))
def patchlistMenuRequest(self, point, selection): self.menuselection = selection menu = QMenu(self) act = QAction(_('Rename patch'), self) act.triggered.connect(self.qrenamePatch) menu.addAction(act) menu.exec_(point)
def __init__(self, repo, parent): QComboBox.__init__(self, parent) self.setEditable(False) self.loaded = False self.default = _('<default>') self.addItem(self.default) self.repo = repo
def commandFinished(self, ret): self.repo.decrementBusyCount() if self.aborted or self.checkResolve() is False: msg = _('Graft is complete') if self.aborted: msg = _('Graft aborted') elif ret == 255: msg = _('Graft failed') self.cmd.setShowOutput(True) # contains hint else: self._updateSource(len(self.sourcelist) - 1) self.showMessage.emit(msg) self.graftbtn.setEnabled(True) self.graftbtn.setText(_('Close')) self.graftbtn.clicked.disconnect(self.graft) self.graftbtn.clicked.connect(self.accept)
def setupUi(self, o): self.editToolbar = QToolBar(self) self.editToolbar.setContextMenuPolicy(Qt.PreventContextMenu) self.addToolBar(Qt.ToolBarArea(Qt.TopToolBarArea), self.editToolbar) self.actionClose = QAction(self) self.actionClose.setShortcuts(QKeySequence.Close) self.actionReload = QAction(self) self.actionReload.setShortcuts(QKeySequence.Refresh) self.editToolbar.addAction(self.actionReload) self.addAction(self.actionClose) self.splitter = QSplitter(Qt.Vertical) self.setCentralWidget(self.splitter) cs = ('fileLogDialog', _('File History Log Columns')) self.repoview = repoview.HgRepoView(self.repo, cs[0], cs, self.splitter) self.repoview.revisionSelectionChanged.connect( self._checkValidSelection) self.contentframe = QFrame(self.splitter) vbox = QVBoxLayout() vbox.setSpacing(0) vbox.setMargin(0) self.contentframe.setLayout(vbox) self.revpanel = revpanel.RevPanelWidget(self.repo) self.revpanel.linkActivated.connect(self.onLinkActivated) vbox.addWidget(self.revpanel, 0) self.textView = fileview.HgFileView(self._repoagent, self) self.textView.revisionSelected.connect(self.goto) vbox.addWidget(self.textView, 1)
def __init__(self, rev, repo, parent): super(BackoutDialog, self).__init__(parent) f = self.windowFlags() self.setWindowFlags(f & ~Qt.WindowContextHelpButtonHint) self.backoutrev = rev self.parentbackout = False self.backoutmergeparentrev = None self.setWindowTitle(_('Backout - %s') % repo.displayname) self.setWindowIcon(qtlib.geticon('hg-revert')) self.setOption(QWizard.NoBackButtonOnStartPage, True) self.setOption(QWizard.NoBackButtonOnLastPage, True) self.setOption(QWizard.IndependentPages, True) self.addPage(SummaryPage(repo, self)) self.addPage(BackoutPage(repo, self)) self.addPage(CommitPage(repo, self)) self.addPage(ResultPage(repo, self)) self.currentIdChanged.connect(self.pageChanged) self.resize(QSize(700, 489).expandedTo(self.minimumSizeHint())) repo.repositoryChanged.connect(self.repositoryChanged) repo.configChanged.connect(self.configChanged)
def refreshCombos(self): shelvea, shelveb = self.currentPatchA(), self.currentPatchB() # Note that thgshelves returns the shelve list ordered from newest to # oldest shelves = self.repo.thgshelves() disp = [_('Shelf: %s') % hglib.tounicode(s) for s in shelves] patches = self.repo.thgmqunappliedpatches disp += [_('Patch: %s') % hglib.tounicode(p) for p in patches] # store fully qualified paths self.shelves = [os.path.join(self.repo.shelfdir, s) for s in shelves] self.patches = [self.repo.mq.join(p) for p in patches] self.comboRefreshInProgress = True self.comboa.clear() self.combob.clear() self.comboa.addItems([self.wdir] + disp) self.combob.addItems(disp) # attempt to restore selection if shelvea == self.wdir: idxa = 0 elif shelvea in self.shelves: idxa = self.shelves.index(shelvea) + 1 elif shelvea in self.patches: idxa = len(self.shelves) + self.patches.index(shelvea) + 1 else: idxa = 0 self.comboa.setCurrentIndex(idxa) if shelveb in self.shelves: idxb = self.shelves.index(shelveb) elif shelveb in self.patches: idxb = len(self.shelves) + self.patches.index(shelveb) else: idxb = 0 self.combob.setCurrentIndex(idxb) self.comboRefreshInProgress = False self.comboAChanged(idxa) self.comboBChanged(idxb) if not patches and not shelves: self.delShelfButtonB.setEnabled(False) self.clearShelfButtonB.setEnabled(False) self.browseb.setContext(patchctx('', self.repo, None))
def version(ui, **opts): """output version and copyright information""" ui.write( _('TortoiseHg Dialogs (version %s), ' 'Mercurial (version %s)\n') % (thgversion.version(), hglib.hgversion)) if not ui.quiet: ui.write(shortlicense)
def updateStates(self): """ update bottom button sensitives based on rev and tag """ tagu = self.tagCombo.currentText() tag = hglib.fromunicode(tagu) # check tag existence if tag: exists = tag in self.repo.tags() if exists: tagtype = self.repo.tagtype(tag) islocal = 'local' == tagtype try: ctx = self.repo[self.repo.tags()[tag]] trev = ctx.rev() thash = str(ctx) except: trev, thash, local = 0, '????????', '' self.localCheckBox.setChecked(islocal) self.localCheckBox.setEnabled(False) local = islocal and _('local') or '' self.tagRevLabel.setText('%d (%s) %s' % (trev, thash, local)) samerev = trev == self.rev else: islocal = self.localCheckBox.isChecked() self.localCheckBox.setEnabled(True) self.tagRevLabel.clear() force = self.replaceCheckBox.isChecked() custom = self.customCheckBox.isChecked() self.addBtn.setEnabled(not exists or (force and not samerev)) if exists and not samerev: self.addBtn.setText(_('Move')) else: self.addBtn.setText(_('Add')) self.removeBtn.setEnabled(exists) self.englishCheckBox.setEnabled(not islocal) self.customCheckBox.setEnabled(not islocal) self.customTextLineEdit.setEnabled(not islocal and custom) else: self.addBtn.setEnabled(False) self.removeBtn.setEnabled(False) self.localCheckBox.setEnabled(False) self.englishCheckBox.setEnabled(False) self.customCheckBox.setEnabled(False) self.customTextLineEdit.setEnabled(False) self.tagRevLabel.clear()
def createActions(self): self.actionClose.triggered.connect(self.close) self.actionReload.triggered.connect(self.reload) self.actionReload.setIcon(qtlib.geticon('view-refresh')) self.actionNextDiff = QAction(qtlib.geticon('go-down'), _('Next diff'), self) self.actionNextDiff.setShortcut('Alt+Down') self.actionNextDiff.triggered.connect(self.nextDiff) self.actionPrevDiff = QAction(qtlib.geticon('go-up'), _('Previous diff'), self) self.actionPrevDiff.setShortcut('Alt+Up') self.actionPrevDiff.triggered.connect(self.prevDiff) self.actionNextDiff.setEnabled(False) self.actionPrevDiff.setEnabled(False)
def reject(self): if self.cmd.core.running(): self.set_status(_('Repository command still running'), False) return # prevent signals from reaching deleted objects self.repo.repositoryChanged.disconnect(self.refresh) super(TagDialog, self).reject()
def reject(self): if self.core.running(): ret = QMessageBox.question(self, _('Confirm Exit'), _('Mercurial command is still running.\n' 'Are you sure you want to terminate?'), QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if ret == QMessageBox.Yes: self.core.cancel() # don't close dialog return # close dialog if self.returnCode == 0: self.accept() # means command successfully finished else: super(Dialog, self).reject()