Status: | Merged |
---|---|
Merge reported by: | Jelmer Vernooij |
Merged at revision: | not available |
Proposed branch: | lp:~saccadic-masking/qbrz/qbrz |
Merge into: | lp:qbrz |
Diff against target: |
88946 lines (+72905/-4332) 156 files modified
.bzrignore (+7/-2) MakeLiterate (+86/-0) Makefile (+234/-20) __init__.py (+11/-3) docs/Makefile (+4/-3) docs/literate/pycco.css (+191/-0) docs/pycco.css (+191/-0) extras/__init__.py (+7/-7) extras/build_mo.py (+12/-11) extras/build_pot.py (+23/-17) extras/build_ui.py (+3/-2) extras/check_py24.py (+1/-1) extras/check_utf8.py (+1/-1) extras/en_po.py (+1/-6) extras/import_po.py (+1/-1) installer/qbrz-setup.iss (+33/-33) iscc (+5/-0) lib/__init__.py (+6/-4) lib/add.py (+58/-61) lib/annotate.py (+114/-119) lib/autocomplete.py (+2/-2) lib/bind.py (+1/-1) lib/branch.py (+5/-5) lib/browse.py (+2/-2) lib/bugs.py (+2/-2) lib/cat.py (+11/-10) lib/cleanup.py (+184/-0) lib/commands.py (+81/-114) lib/commit.py (+102/-96) lib/commit_data.py (+5/-5) lib/conditional_dataview.py (+3/-3) lib/config.py (+115/-120) lib/conflicts.py (+14/-14) lib/decorators.py (+2/-2) lib/diff.py (+72/-68) lib/diffview.py (+51/-58) lib/diffwindow.py (+24/-21) lib/encoding_selector.py (+11/-9) lib/export.py (+8/-8) lib/extra/bugurl.py (+4/-7) lib/extra/isignored.py (+2/-2) lib/extra/isversioned.py (+2/-2) lib/fake_branch.py (+1/-1) lib/getnew.py (+6/-6) lib/getupdates.py (+4/-4) lib/html_log.py (+15/-4) lib/i18n.py (+5/-2) lib/ignore.py (+8/-8) lib/info.py (+3/-3) lib/init.py (+5/-5) lib/lazycachedrevloader.py (+3/-3) lib/log.py (+207/-190) lib/loggraphviz.py (+269/-269) lib/logmodel.py (+24/-24) lib/logwidget.py (+118/-141) lib/main.py (+57/-61) lib/plugins.py (+2/-4) lib/pull.py (+11/-14) lib/resources.py (+3/-3) lib/revert.py (+25/-29) lib/revisionmessagebrowser.py (+59/-57) lib/revtreeview.py (+45/-58) lib/run.py (+45/-72) lib/send.py (+7/-7) lib/shelvewindow.py (+8/-13) lib/spellcheck.py (+1/-1) lib/spellcheck_enchant.py (+1/-1) lib/statuscache.py (+20/-17) lib/subprocess.py (+410/-245) lib/switch.py (+3/-3) lib/syntaxhighlighter.py (+1/-1) lib/sysinfo.py (+6/-7) lib/sysinfo_data.py (+6/-6) lib/tag.py (+7/-7) lib/tests/__init__.py (+11/-6) lib/tests/mock.py (+6/-6) lib/tests/modeltest.py (+86/-32) lib/tests/test_annotate.py (+19/-19) lib/tests/test_autocomplete.py (+2/-3) lib/tests/test_bugs.py (+31/-29) lib/tests/test_cat.py (+6/-1) lib/tests/test_commit.py (+4/-0) lib/tests/test_commit_data.py (+9/-13) lib/tests/test_decorator.py (+1/-1) lib/tests/test_diffview.py (+11/-11) lib/tests/test_extdiff.py (+24/-32) lib/tests/test_extra_isignored.py (+5/-4) lib/tests/test_extra_isversioned.py (+4/-4) lib/tests/test_guidebar.py (+50/-32) lib/tests/test_i18n.py (+6/-4) lib/tests/test_log.py (+21/-33) lib/tests/test_loggraphviz.py (+394/-396) lib/tests/test_logmodel.py (+10/-19) lib/tests/test_revisionmessagebrowser.py (+2/-2) lib/tests/test_spellcheck.py (+7/-7) lib/tests/test_subprocess.py (+78/-61) lib/tests/test_treewidget.py (+176/-155) lib/tests/test_util.py (+110/-109) lib/texteditannotate.py (+4/-4) lib/trace.py (+45/-48) lib/tree_branch.py (+1/-1) lib/treewidget.py (+599/-508) lib/ui_bookmark.py (+27/-16) lib/ui_branch.py (+20/-14) lib/ui_info.py (+21/-12) lib/ui_init.py (+65/-54) lib/ui_merge.py (+36/-25) lib/ui_merge_config.py (+32/-20) lib/ui_new_tree.py (+81/-70) lib/ui_pull.py (+34/-23) lib/ui_push.py (+2/-1) lib/ui_run.py (+49/-39) lib/ui_sysinfo.py (+75/-84) lib/ui_tag.py (+52/-35) lib/ui_update_branch.py (+48/-31) lib/ui_update_checkout.py (+36/-25) lib/ui_verify_signatures.py (+11/-3) lib/uifactory.py (+1/-1) lib/uncommit.py (+12/-24) lib/util.py (+102/-85) lib/verify_signatures.py (+16/-29) lib/widgets/shelve.py (+7/-7) lib/widgets/shelvelist.py (+3/-3) lib/widgets/tab_width_selector.py (+4/-4) lib/widgets/texteditaccessory.py (+3/-3) lib/win32util.py (+2/-2) po/qbrz-ar.po (+2380/-0) po/qbrz-cs.po (+2379/-0) po/qbrz-da.po (+2406/-0) po/qbrz-de.po (+2543/-0) po/qbrz-en.po (+2435/-0) po/qbrz-en_GB.po (+2532/-0) po/qbrz-es.po (+2522/-0) po/qbrz-et.po (+2516/-0) po/qbrz-fr.po (+2434/-0) po/qbrz-gl.po (+2385/-0) po/qbrz-he.po (+2394/-0) po/qbrz-hu.po (+2391/-0) po/qbrz-it.po (+2514/-0) po/qbrz-ja.po (+2508/-0) po/qbrz-nl.po (+2481/-0) po/qbrz-pl.po (+2496/-0) po/qbrz-pt_BR.po (+2436/-0) po/qbrz-ru.po (+2514/-0) po/qbrz-sk.po (+2386/-0) po/qbrz-sl.po (+2380/-0) po/qbrz-sr.po (+2380/-0) po/qbrz-sv.po (+2382/-0) po/qbrz-th.po (+2379/-0) po/qbrz-tr.po (+2411/-0) po/qbrz-uk.po (+2396/-0) po/qbrz.pot (+2375/-0) qbrz-0.23.2-20191027brz1531-fix_pyqt412.patch (+3923/-0) run-tests.sh (+2/-1) setup.py (+20/-7) ui/sysinfo.ui (+67/-66) |
To merge this branch: | bzr merge lp:~saccadic-masking/qbrz/qbrz |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Robert Ladyman | Approve | ||
Breezy developers | Pending | ||
Review via email: mp+387526@code.launchpad.net |
Commit message
Updated to work with Python3: still using PyQt4. Applied Olaf Seibert's and Yasuyuki Furukawa's suggested changes. Note that, for me, qmain, qverify-signatures and qhelp did not work with bzr, so have not been fully updated.
Description of the change
Jelmer Vernooij (jelmer) wrote : | # |
Robert Ladyman (saccadic-masking) wrote : | # |
Dear Jelmer,
It's the old code updated. I have taken the code changes by Olaf Seibert
(He ran 2 to 3 to convert to Python3), applied (partially) the patch
from Yasuyuki Furukawa to slightly update the PyQt4 calls:
(https:/
and then worked at it all to get the tests to pass and then to test each
command (as the tests often passed even if the code failed). My hair is
now even more grey.
If it's too big to merge, it might be easier to replace trunk with this
(the old trunk doesn't work in Python 3 anyway). Almost every file has
been changed, including Makefiles: I managed to use the old translation
files without change, so it also works in the other languages (although
they will need QBzr / Bazaar changed to QBrz / Breezy, which I can do)
and have updated the release mechanism so there is an .exe as well as a
.tar.gz (I can't test the .exe though).
I have not updated all the brz references nor the Author / Readme files
yet: wasn't certain it would be accepted or work well enough.
I'll update it with the textual changes, etc. I expect that there are
the odd bits that are still broken, but I am using this now every day
and about to rewrite two of our own tools (EasyBreezy and bzr-xmpp) for
Breezy: I will apply bug-fixes as I go.
I cannot test it on Windows, as I've discovered, so am now looking at
the brz code, which I note has a whole tools/win32 section with the old
bazaar Makefiles, etc., in it, to get a working Breezy .exe to install.
Regards,
RJL
P.S. the literate documentation is produced by pycco, which sometimes
gets things horribly wrong. I'll fix pycco later and re-run it then.
Another project.
On 16/07/2020 21:08, Jelmer Vernooij wrote:
> Awesome, this is great to see!
>
> I'm not entirely sure how to go about reviewing this since it's so large - it exceeds the 5000 line limit from Launchpad. I don't think it's realistic to review everything in detail so perhaps we can just stick to the higher level bits.
>
> Are you the author of all of the files that are being added, including e.g. the css files?
>
--
Robert Ladyman
HunterBirnie
Tel: +44 (0) 1828 898 158
Mobile: +44 (0) 7732 771 649
http://
PGP: E40A2EE2AA9991E7
*******
HunterBirnie is a trading name of File-Away Limited
Registered in Scotland, Company Number: SC222086
Registered address: 30 Church St, Newtyle PH128TZ
Robert Ladyman (saccadic-masking) wrote : | # |
To add: pycco creates the CSS files.
Jelmer Vernooij (jelmer) wrote : | # |
Yeah, replacing trunk with your branch is probably the best option.
I don't think I'll have time to do a meaningful review, and if I did do that I'm not sure whether that would be a valuable use of your or my time. I also don't have a good way of running qbrz myself, since python3-pyqt4 is no longer available on Debian.
Let me create a new team for qbrz and add you to that, and then we can pull your changes into trunk. I'm happy to review incremental changes on top of this branch if you think that would be useful, but otherwise feel free to just directly push to trunk.
Robert Ladyman (saccadic-masking) wrote : | # |
OK, that seems easiest: plus it means I can fix any lurking problems that I find as I use it and keep it in step with breezy itself. The patches will be smaller in future.
Robert Ladyman (saccadic-masking) : | # |
Preview Diff
1 | === modified file '.bzrignore' |
2 | --- .bzrignore 2010-10-11 15:20:54 +0000 |
3 | +++ .bzrignore 2020-07-16 14:28:25 +0000 |
4 | @@ -2,6 +2,11 @@ |
5 | ./build |
6 | ./docs/**/*.html |
7 | ./launchpad-export.tar.gz |
8 | -./locale |
9 | -./MANIFEST |
10 | tags |
11 | +*.tar.gz |
12 | +*.tar.gz.asc |
13 | +.vscode/bookmarks.json |
14 | +.vscode |
15 | +qbrz-setup-iss.log |
16 | +*.exe |
17 | +*.exe.asc |
18 | |
19 | === added file 'MakeLiterate' |
20 | --- MakeLiterate 1970-01-01 00:00:00 +0000 |
21 | +++ MakeLiterate 2020-07-16 14:28:25 +0000 |
22 | @@ -0,0 +1,86 @@ |
23 | +# RJL: This will make literate documents via pycco in docs/literate |
24 | +# Run this makefile via |
25 | +# |
26 | +# make -f MakeLiterate... |
27 | +# |
28 | +# You should note that pycco gets confused sometimes and its output |
29 | +# can be a little garbled, but it can help to understand other |
30 | +# people's code more easily. |
31 | + |
32 | +MAKEFLAGS += --warn-undefined-variables |
33 | +MAKEFLAGS += --no-builtin-rules |
34 | + |
35 | +RST2HTML := rst2html5.py --initial-header-level=2 --footnote-references=superscript --smart-quotes=yes -g -d -t |
36 | +PDOC := pdoc --html --overwrite --all-submodules --html-dir |
37 | + |
38 | +# Updated by RJL 13th May with more sensible behaviour |
39 | +# For some reason it won't generate SQL files |
40 | + |
41 | +# We build or rebuild the documentation with pycco - shorthand for the command here in PYCCO_ALL variable |
42 | +# This one builds the index.html file |
43 | +PYCCO_ALL := pycco --generate_index --paths -s --directory |
44 | + |
45 | +# This one does NOT build the index file - otherwise, if you pass a single file |
46 | +# it will be the ONLY one in the index. Do'h! |
47 | +PYCCO_ONE := pycco --paths -s --directory |
48 | + |
49 | + |
50 | +# We want to look at all the .py files in the Code directory (where we start) |
51 | +# in case any have changed. The makefile is in /Code so we just use './' |
52 | +# the shell for 'this directory that we are in' - so the following means |
53 | +# 'all the files ending in "py" in this directory' |
54 | +PYSOURCES=$(wildcard *.py) |
55 | + |
56 | +PYSUBSOURCES=$(wildcard lib/*.py) |
57 | +PYTESTSOURCES=$(wildcard lib/tests/*.py) |
58 | +PYWIDGESTSOURCES=$(wildcard lib/widgets/*.py) |
59 | +PYEXTRASOURCES=$(wildcard lib/extra/*.py) |
60 | + |
61 | +ALL_SOURCES=$(PYSOURCES) $(PYSUBSOURCES) $(PYTESTSOURCES) $(PYWIDGESTSOURCES) $(PYEXTRASOURCES) |
62 | + |
63 | +# This is how we extract an html file-name for each changed python file-name |
64 | +# It basically reads: for each .py file in the source directory (PYSOURCES), |
65 | +# there should be a matching .html file in Code_Documentation. |
66 | +# The % means the stem, for example world.py has a stem of 'world' so we |
67 | +# make world.html from world.py |
68 | +DOCUMENTS_NEEDED_BASE=$(PYSOURCES:%.py=docs/literate/%.html) |
69 | + |
70 | +# For subdirectories, we'll get the subdirectory as a prefix |
71 | +# for example, lib/widgets |
72 | +DOCUMENTS_NEEDED_SUB=$(PYSUBSOURCES:%.py=docs/literate/%.html) |
73 | + |
74 | +# What to do if we just type 'make' without any parameters - we generate the docs |
75 | +.DEFAULT_GOAL := all |
76 | + |
77 | +# No such file as all so mark it as a phony |
78 | +.PHONY: all |
79 | +.PHONY: base |
80 | +.PHONY: svrsub |
81 | + |
82 | +.PHONY: sqlfiles |
83 | + |
84 | +base: $(DOCUMENTS_NEEDED_BASE) |
85 | +svrsub: $(DOCUMENTS_NEEDED_SUB) |
86 | + |
87 | +all: sqlfiles base svrsub |
88 | + |
89 | +# The html file in docs/literate (and its cousins) depends upon the py file of the same name |
90 | +# If the html file is missing or older than the python one, run the pycco command |
91 | +# for the file (in $<) |
92 | + |
93 | +docs/literate/lib/%.html: %.py |
94 | + $(PYCCO_ONE) ./docs/literate $< |
95 | + |
96 | +docs/literate/%.html: %.py |
97 | + $(PYCCO_ONE) ./docs/literate $< |
98 | + |
99 | +# Call 'make index' to make the full documentation |
100 | +.PHONY: index |
101 | +index: |
102 | + make clean |
103 | + $(PYCCO_ALL) ./docs/literate $(ALL_SOURCES) |
104 | + |
105 | +.PHONY: clean |
106 | +clean: |
107 | + rm -rf docs/literate |
108 | + |
109 | |
110 | === modified file 'Makefile' |
111 | --- Makefile 2018-01-31 22:46:16 +0000 |
112 | +++ Makefile 2020-07-16 14:28:25 +0000 |
113 | @@ -1,3 +1,4 @@ |
114 | + |
115 | all: |
116 | @echo Targets: |
117 | @echo test - run tests |
118 | @@ -8,36 +9,42 @@ |
119 | @echo docs - build htmls for texts in docs/ directory |
120 | @echo epydoc - build API docs with epydoc |
121 | @echo ui - compile UI files |
122 | + @echo inno - compile exe (pass RELEASE=X.Y.Z) |
123 | @echo |
124 | @echo To build release run: |
125 | @echo make release RELEASE=X.Y.Z |
126 | |
127 | .PHONY: test pot mo clean tags docs ui |
128 | |
129 | -check: test |
130 | - BRZ_PLUGINS_AT=qbrz@$(shell pwd) brz selftest -s bp.qbrz |
131 | - |
132 | -test: |
133 | - brz selftest -s bp.qbzr |
134 | - |
135 | -pot: |
136 | - python setup.py build_pot -N -d. |
137 | +# Making pot files is disabled for now - no translators! |
138 | +# pot: |
139 | +# python3 setup.py build_pot -N -d. |
140 | + |
141 | +.check-env-vars: |
142 | + @test $${RELEASE?RELEASE is undefined. To build release run make release with RELEASE=X.Y.Z} |
143 | |
144 | mo: |
145 | - python setup.py build_mo -f |
146 | - |
147 | -tarball: |
148 | - bzr export --root=qbzr qbzr-$(RELEASE).tar.gz |
149 | - gpg -ab qbzr-$(RELEASE).tar.gz |
150 | - |
151 | -inno: mo |
152 | - iscc installer/qbzr-setup.iss |
153 | - gpg -ab qbzr-setup-$(RELEASE).exe |
154 | - |
155 | + python3 setup.py build_mo -f --verbose |
156 | + |
157 | +tarball: .check-env-vars |
158 | + brz export --root=qbrz qbrz-$(RELEASE).tar.gz |
159 | + rm -f qbrz-$(RELEASE).tar.gz.asc |
160 | + gpg2 -ab qbrz-$(RELEASE).tar.gz |
161 | + |
162 | +# RJL needs to come back in |
163 | +# inno: mo |
164 | +# ./iscc installer/qbrz-setup.iss |
165 | +# gpg -ab qbrz-setup-$(RELEASE).exe |
166 | +inno: .check-env-vars |
167 | + ./iscc installer/qbrz-setup.iss |
168 | + rm -f qbrz-setup-$(RELEASE).exe.asc |
169 | + gpg2 -ab qbrz-setup-$(RELEASE).exe |
170 | + |
171 | +# release: tarball inno |
172 | release: tarball inno |
173 | |
174 | clean: |
175 | - python setup.py clean -a |
176 | + python3 setup.py clean -a |
177 | |
178 | tags: |
179 | ctags *.py lib/*.py lib/extra/*.py lib/tests/*.py |
180 | @@ -49,4 +56,211 @@ |
181 | $(MAKE) -C docs |
182 | |
183 | ui: |
184 | - python setup.py build_ui |
185 | + python3 setup.py build_ui |
186 | + |
187 | + |
188 | +# === Tests beyond this point === |
189 | + |
190 | +check: test |
191 | + BRZ_PLUGINS_AT=qbrz@$(shell pwd) brz selftest -s bp.qbrz -x TestTreeFilterProxyModel |
192 | + |
193 | +# Stop on first error, ignore TestTreeFilterProxyModel for now |
194 | + |
195 | +checkone: test |
196 | + BRZ_PLUGINS_AT=qbrz@$(shell pwd) brz selftest -v --one -s bp.qbrz -x TestTreeFilterProxyModel |
197 | + |
198 | +# Test specific item - e.g. for internationalisation, use: |
199 | +# |
200 | +# BRZ_PLUGINS_AT=qbrz@$(shell pwd) brz selftest --one --strict -s bp.qbrz TestI18n |
201 | +checkspecific: test |
202 | + BRZ_PLUGINS_AT=qbrz@$(shell pwd) brz selftest --one --strict -s bp.qbrz TestBencode |
203 | + |
204 | +# Rather than running the test_ suite, this lets you run the actual plugin - note |
205 | +# that the tests can often pass but the code fails in actual use. |
206 | +qtest: |
207 | +# You can test on qbrz itself like this (qlog in this example): |
208 | +# |
209 | + BRZ_PLUGINS_AT=qbrz@$(shell pwd) brz qdiff |
210 | +# |
211 | +# If you have a test directory you wish to use, you can cd to it, run the code, cd back from it. |
212 | +# In this example, we have a test dir of ``~/pythonstuff/bzr_test_dir/sopsteward`` - we have |
213 | +# to ``cd`` to it (note the semi-colon) THEN execute the plugin code we want: |
214 | +# |
215 | +# cd ~/pythonstuff/bzr_test_dir/sopsteward; BRZ_PLUGINS_AT=qbrz@/home/rjl/pythonstuff/fix-python-etc brz qdiff |
216 | + |
217 | +test: |
218 | + brz selftest -s bp.qbrz |
219 | + |
220 | + |
221 | +# Fully working: (note, qcheckout-ala-explorer is qgetn). |
222 | +# qlog |
223 | +# qadd |
224 | +# qannotate, qblame |
225 | +# qcommit |
226 | +# qbrowse |
227 | +# qcat, qviewer |
228 | +# qversion |
229 | +# qplugins |
230 | +# qinit |
231 | +# qbranch |
232 | +# qbind |
233 | +# qunbind |
234 | +# qignore |
235 | +# qinfo |
236 | +# qupdate |
237 | +# quncommit |
238 | +# qpull |
239 | +# qshelve |
240 | +# qunshelve |
241 | +# qtag |
242 | +# qgetn |
243 | +# qrevert |
244 | +# qpush |
245 | +# qsend |
246 | +# qmerge |
247 | +# qconflicts |
248 | +# qresolve |
249 | +# qswitch |
250 | +# qcmd |
251 | +# qsubprocess |
252 | +# qdiff |
253 | +# qconfig |
254 | + |
255 | + |
256 | +# === qmain === |
257 | + |
258 | +# qmain fails in bzr |
259 | + |
260 | + |
261 | +# === qverify-signatures === |
262 | + |
263 | +# qverify-signatures fails in bzr |
264 | + |
265 | + |
266 | +# === qhelp === |
267 | + |
268 | +# qhelp doesn't work for me even in bzr |
269 | + |
270 | + |
271 | +# === Items in Plug-ins === |
272 | + |
273 | +# NOT working |
274 | +# qinit-workspace, qnew also unknown - they appear to be from the 'explorer' plugin |
275 | + |
276 | + |
277 | +# === Literate documentation, etc === |
278 | + |
279 | +# This uses pycco to generate the literal documentation. |
280 | +# To rebuild all of it, with an index.html file, use: |
281 | +# |
282 | +# make literate_index |
283 | +# |
284 | +# To just update (although new files won't be added to index.html), use: |
285 | +# |
286 | +# make literate_docs |
287 | +# |
288 | +# otherwise, you can just make the base, lib, or whatever using (for example): |
289 | +# |
290 | +# make widget_docs |
291 | +# |
292 | +# Output goes into docs/literate/... mirroring the source-code locations (e.g. |
293 | +# lib/widgets/... go into docs/literate/lib/widgets |
294 | +# |
295 | +# pycco isn't brilliant, but it tries its best |
296 | + |
297 | +# We build or rebuild the documentation with pycco - shorthand for the command here in PYCCO_ALL variable |
298 | +# This one builds the index.html file |
299 | +PYCCO_ALL := pycco --generate_index --paths -s --directory |
300 | + |
301 | +# This one does NOT build the index file - otherwise, if you pass a single file |
302 | +# it will be the ONLY one in the index. Do'h! |
303 | +PYCCO_ONE := pycco --paths -s --directory |
304 | + |
305 | +# We want to look at all the .py files in the Code directory (where we start) |
306 | +# in case any have changed. The makefile is in /Code so we just use './' |
307 | +# the shell for 'this directory that we are in' - so the following means |
308 | +# 'all the files ending in "py" in this directory' |
309 | +PYMAINSOURCES=$(wildcard ./*.py) |
310 | +# The lib sources |
311 | +PYLIBSOURCES=$(wildcard ./lib/*.py) |
312 | +# extras and tests |
313 | +PYEXTRASOURCES=$(wildcard ./lib/extra/*.py) |
314 | +PYEXTRASSOURCES=$(wildcard ./extras/*.py) |
315 | +PYTESTSSOURCES=$(wildcard ./lib/tests/*.py) |
316 | +PYWIDGETSOURCES=$(wildcard ./lib/widgets/*.py) |
317 | + |
318 | +# So now add them all together |
319 | +PYSOURCES=$(PYMAINSOURCES) $(PYLIBSOURCES) $(PYEXTRASOURCES) $(PYEXTRASSOURCES) $(PYTESTSSOURCES) $(PYWIDGETSOURCES) |
320 | + |
321 | +# This is how we extract an html file-name for each changed python file-name |
322 | +# It basically reads: for each .py file in the source directory (PYSOURCES), |
323 | +# there should be a matching .html file in Code_Documentation. |
324 | +# The % means the stem, for example world.py has a stem of 'world' so we |
325 | +# make world.html from world.py |
326 | +DOCUMENTS_NEEDED_BASE=$(PYSOURCES:%.py=docs/literate/%.html) |
327 | + |
328 | +# For subdirectories, we'll get the subdirectory as a prefix |
329 | +# for example, svrsub/svrconfig |
330 | +DOCUMENTS_NEEDED_LIB=$(PYLIBSOURCES:%.py=docs/literate/%.html) |
331 | +DOCUMENTS_NEEDED_EXTRA=$(PYEXTRASOURCES:%.py=docs/literate/%.html) |
332 | +DOCUMENTS_NEEDED_EXTRAS=$(PYEXTRASSOURCES:%.py=docs/literate/%.html) |
333 | +DOCUMENTS_NEEDED_TEST=$(PYTESTSSOURCES:%.py=docs/literate/%.html) |
334 | +DOCUMENTS_NEEDED_WIDGETS=$(PYWIDGETSOURCES:%.py=docs/literate/%.html) |
335 | + |
336 | +.PHONY: literate_docs |
337 | +# No such file as all so mark it as a phony |
338 | +.PHONY: base_docs |
339 | +.PHONY: lib_docs |
340 | +.PHONY: extra_docs |
341 | +.PHONY: extras_docs |
342 | +.PHONY: test_docs |
343 | +.PHONY: widget_docs |
344 | + |
345 | +base_docs: $(DOCUMENTS_NEEDED_BASE) |
346 | +lib_docs: $(DOCUMENTS_NEEDED_LIB) |
347 | +extra_docs: $(DOCUMENTS_NEEDED_EXTRA) |
348 | +extras_docs: $(DOCUMENTS_NEEDED_EXTRAS) |
349 | +test_docs: $(DOCUMENTS_NEEDED_TEST) |
350 | +widget_docs: $(DOCUMENTS_NEEDED_WIDGETS) |
351 | + |
352 | +literate_docs: base_docs lib_docs extra_docs extras_docs test_docs widget_docs |
353 | + |
354 | +# The html file in docs/literate (and its cousins) depends upon the py file of the same name |
355 | +# If the html file is missing or older than the python one, run the pycco command |
356 | +# for the file (in $<) |
357 | + |
358 | + |
359 | + |
360 | +docs/literate/%.html: %.py |
361 | + $(PYCCO_ONE) ./docs/literate $< |
362 | + |
363 | + |
364 | +docs/literate/extras/%.html: %.py |
365 | + $(PYCCO_ONE) ./docs/literate $< |
366 | + |
367 | +docs/literate/lib/%.html: %.py |
368 | + $(PYCCO_ONE) ./docs/literate $< |
369 | + |
370 | + |
371 | +docs/literate/lib/data/%.html: %.py |
372 | + $(PYCCO_ONE) ./docs/literate $< |
373 | + |
374 | +docs/literate/lib/extra/%.html: %.py |
375 | + $(PYCCO_ONE) ./docs/literate $< |
376 | + |
377 | +docs/literate/lib/test/%.html: %.py |
378 | + $(PYCCO_ONE) ./docs/literate $< |
379 | + |
380 | +docs/literate/lib/widgets/%.html: %.py |
381 | + $(PYCCO_ONE) ./docs/literate $< |
382 | + |
383 | +# Call 'make index' to make the full documentation |
384 | +.PHONY: literate_index |
385 | +literate_index: |
386 | + make literate_clean |
387 | + $(PYCCO_ALL) ./docs/literate $(PYSOURCES) |
388 | + |
389 | +.PHONY: literate_clean |
390 | +literate_clean: |
391 | + rm -rf docs/literate/ |
392 | + |
393 | |
394 | === modified file '__init__.py' |
395 | --- __init__.py 2017-09-11 06:53:22 +0000 |
396 | +++ __init__.py 2020-07-16 14:28:25 +0000 |
397 | @@ -1,3 +1,4 @@ |
398 | +#!/usr/bin/python3 -bb |
399 | # -*- coding: utf-8 -*- |
400 | # |
401 | # QBzr - Qt frontend to Bazaar commands |
402 | @@ -70,11 +71,19 @@ |
403 | Miscellaneous: |
404 | |
405 | * bug-url - print full URL to a specific bug, or open it in your browser. |
406 | + |
407 | +RJL 2020: |
408 | +This is the updated version for QBrz |
409 | """ |
410 | |
411 | -from __future__ import absolute_import |
412 | +# RJL to speed development, retain Qt4 for now: use ``sip.setapi`` to request |
413 | +# version 1 behaviour for ``QVariant`` (otherwise it's not available for python3) |
414 | +import sip |
415 | +sip.setapi('QVariant', 2) |
416 | |
417 | -version_info = (0,23,2,'final',0) |
418 | +# RJL: set to 0,3,1 to match br |
419 | +# version_info = (0,23,2,'final',0) |
420 | +version_info = (0,3,1,'dev',0) |
421 | __version__ = '.'.join(map(str, version_info)) |
422 | |
423 | |
424 | @@ -82,7 +91,6 @@ |
425 | |
426 | from breezy.commands import plugin_cmds |
427 | |
428 | - |
429 | # merge --qpreview disabled for 0.14 because it makes qbrz incompatible with bzr-pipeline plugin |
430 | # see bug https://bugs.launchpad.net/bugs/395817 |
431 | #register_lazy_command('breezy.plugins.qbrz.lib.commands', 'cmd_merge', [], decorate=True) # provides merge --qpreview |
432 | |
433 | === modified file 'docs/Makefile' |
434 | --- docs/Makefile 2010-05-12 12:20:13 +0000 |
435 | +++ docs/Makefile 2020-07-16 14:28:25 +0000 |
436 | @@ -2,13 +2,14 @@ |
437 | |
438 | all: html |
439 | |
440 | -rst2html := python rst2html.py |
441 | +# rst2html := python rst2html.py |
442 | +RST2HTML := rst2html5.py --initial-header-level=2 --footnote-references=superscript --smart-quotes=yes -g -d -t |
443 | |
444 | %.html: %.txt |
445 | - $(rst2html) $< $@ |
446 | + $(RST2HTML) $< $@ |
447 | |
448 | %.html: ../%.txt |
449 | - $(rst2html) $< $@ |
450 | + $(RST2HTML) $< $@ |
451 | |
452 | html: index.html gettext_usage.html make_release.html \ |
453 | slot-signal-mini-tutorial/slot-signal-mini-tutorial.html \ |
454 | |
455 | === added directory 'docs/literate' |
456 | === added directory 'docs/literate/extras' |
457 | === added directory 'docs/literate/lib' |
458 | === added directory 'docs/literate/lib/extra' |
459 | === added directory 'docs/literate/lib/tests' |
460 | === added directory 'docs/literate/lib/widgets' |
461 | === added file 'docs/literate/pycco.css' |
462 | --- docs/literate/pycco.css 1970-01-01 00:00:00 +0000 |
463 | +++ docs/literate/pycco.css 2020-07-16 14:28:25 +0000 |
464 | @@ -0,0 +1,191 @@ |
465 | +/*--------------------- Layout and Typography ----------------------------*/ |
466 | +body { |
467 | + font-family: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif; |
468 | + font-size: 16px; |
469 | + line-height: 24px; |
470 | + color: #252519; |
471 | + margin: 0; padding: 0; |
472 | + background: #f5f5ff; |
473 | +} |
474 | +a { |
475 | + color: #261a3b; |
476 | +} |
477 | + a:visited { |
478 | + color: #261a3b; |
479 | + } |
480 | +p { |
481 | + margin: 0 0 15px 0; |
482 | +} |
483 | +h1, h2, h3, h4, h5, h6 { |
484 | + margin: 40px 0 15px 0; |
485 | +} |
486 | +h2, h3, h4, h5, h6 { |
487 | + margin-top: 0; |
488 | + } |
489 | +#container { |
490 | + background: white; |
491 | + } |
492 | +#container, div.section { |
493 | + position: relative; |
494 | +} |
495 | +#background { |
496 | + position: absolute; |
497 | + top: 0; left: 580px; right: 0; bottom: 0; |
498 | + background: #f5f5ff; |
499 | + border-left: 1px solid #e5e5ee; |
500 | + z-index: 0; |
501 | +} |
502 | +#jump_to, #jump_page { |
503 | + background: white; |
504 | + -webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777; |
505 | + -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px; |
506 | + font: 10px Arial; |
507 | + text-transform: uppercase; |
508 | + cursor: pointer; |
509 | + text-align: right; |
510 | +} |
511 | +#jump_to, #jump_wrapper { |
512 | + position: fixed; |
513 | + right: 0; top: 0; |
514 | + padding: 5px 10px; |
515 | +} |
516 | + #jump_wrapper { |
517 | + padding: 0; |
518 | + display: none; |
519 | + } |
520 | + #jump_to:hover #jump_wrapper { |
521 | + display: block; |
522 | + } |
523 | + #jump_page { |
524 | + padding: 5px 0 3px; |
525 | + margin: 0 0 25px 25px; |
526 | + } |
527 | + #jump_page .source { |
528 | + display: block; |
529 | + padding: 5px 10px; |
530 | + text-decoration: none; |
531 | + border-top: 1px solid #eee; |
532 | + } |
533 | + #jump_page .source:hover { |
534 | + background: #f5f5ff; |
535 | + } |
536 | + #jump_page .source:first-child { |
537 | + } |
538 | +div.docs { |
539 | + float: left; |
540 | + max-width: 500px; |
541 | + min-width: 500px; |
542 | + min-height: 5px; |
543 | + padding: 10px 25px 1px 50px; |
544 | + vertical-align: top; |
545 | + text-align: left; |
546 | +} |
547 | + .docs pre { |
548 | + margin: 15px 0 15px; |
549 | + padding-left: 15px; |
550 | + overflow-y: scroll; |
551 | + } |
552 | + .docs p tt, .docs p code { |
553 | + background: #f8f8ff; |
554 | + border: 1px solid #dedede; |
555 | + font-size: 12px; |
556 | + padding: 0 0.2em; |
557 | + } |
558 | + .octowrap { |
559 | + position: relative; |
560 | + } |
561 | + .octothorpe { |
562 | + font: 12px Arial; |
563 | + text-decoration: none; |
564 | + color: #454545; |
565 | + position: absolute; |
566 | + top: 3px; left: -20px; |
567 | + padding: 1px 2px; |
568 | + opacity: 0; |
569 | + -webkit-transition: opacity 0.2s linear; |
570 | + } |
571 | + div.docs:hover .octothorpe { |
572 | + opacity: 1; |
573 | + } |
574 | +div.code { |
575 | + margin-left: 580px; |
576 | + padding: 14px 15px 16px 50px; |
577 | + vertical-align: top; |
578 | +} |
579 | + .code pre, .docs p code { |
580 | + font-size: 12px; |
581 | + } |
582 | + pre, tt, code { |
583 | + line-height: 18px; |
584 | + font-family: Monaco, Consolas, "Lucida Console", monospace; |
585 | + margin: 0; padding: 0; |
586 | + } |
587 | +div.clearall { |
588 | + clear: both; |
589 | +} |
590 | + |
591 | + |
592 | +/*---------------------- Syntax Highlighting -----------------------------*/ |
593 | +td.linenos { background-color: #f0f0f0; padding-right: 10px; } |
594 | +span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; } |
595 | +body .hll { background-color: #ffffcc } |
596 | +body .c { color: #408080; font-style: italic } /* Comment */ |
597 | +body .err { border: 1px solid #FF0000 } /* Error */ |
598 | +body .k { color: #954121 } /* Keyword */ |
599 | +body .o { color: #666666 } /* Operator */ |
600 | +body .cm { color: #408080; font-style: italic } /* Comment.Multiline */ |
601 | +body .cp { color: #BC7A00 } /* Comment.Preproc */ |
602 | +body .c1 { color: #408080; font-style: italic } /* Comment.Single */ |
603 | +body .cs { color: #408080; font-style: italic } /* Comment.Special */ |
604 | +body .gd { color: #A00000 } /* Generic.Deleted */ |
605 | +body .ge { font-style: italic } /* Generic.Emph */ |
606 | +body .gr { color: #FF0000 } /* Generic.Error */ |
607 | +body .gh { color: #000080; font-weight: bold } /* Generic.Heading */ |
608 | +body .gi { color: #00A000 } /* Generic.Inserted */ |
609 | +body .go { color: #808080 } /* Generic.Output */ |
610 | +body .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ |
611 | +body .gs { font-weight: bold } /* Generic.Strong */ |
612 | +body .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ |
613 | +body .gt { color: #0040D0 } /* Generic.Traceback */ |
614 | +body .kc { color: #954121 } /* Keyword.Constant */ |
615 | +body .kd { color: #954121; font-weight: bold } /* Keyword.Declaration */ |
616 | +body .kn { color: #954121; font-weight: bold } /* Keyword.Namespace */ |
617 | +body .kp { color: #954121 } /* Keyword.Pseudo */ |
618 | +body .kr { color: #954121; font-weight: bold } /* Keyword.Reserved */ |
619 | +body .kt { color: #B00040 } /* Keyword.Type */ |
620 | +body .m { color: #666666 } /* Literal.Number */ |
621 | +body .s { color: #219161 } /* Literal.String */ |
622 | +body .na { color: #7D9029 } /* Name.Attribute */ |
623 | +body .nb { color: #954121 } /* Name.Builtin */ |
624 | +body .nc { color: #0000FF; font-weight: bold } /* Name.Class */ |
625 | +body .no { color: #880000 } /* Name.Constant */ |
626 | +body .nd { color: #AA22FF } /* Name.Decorator */ |
627 | +body .ni { color: #999999; font-weight: bold } /* Name.Entity */ |
628 | +body .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ |
629 | +body .nf { color: #0000FF } /* Name.Function */ |
630 | +body .nl { color: #A0A000 } /* Name.Label */ |
631 | +body .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ |
632 | +body .nt { color: #954121; font-weight: bold } /* Name.Tag */ |
633 | +body .nv { color: #19469D } /* Name.Variable */ |
634 | +body .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ |
635 | +body .w { color: #bbbbbb } /* Text.Whitespace */ |
636 | +body .mf { color: #666666 } /* Literal.Number.Float */ |
637 | +body .mh { color: #666666 } /* Literal.Number.Hex */ |
638 | +body .mi { color: #666666 } /* Literal.Number.Integer */ |
639 | +body .mo { color: #666666 } /* Literal.Number.Oct */ |
640 | +body .sb { color: #219161 } /* Literal.String.Backtick */ |
641 | +body .sc { color: #219161 } /* Literal.String.Char */ |
642 | +body .sd { color: #219161; font-style: italic } /* Literal.String.Doc */ |
643 | +body .s2 { color: #219161 } /* Literal.String.Double */ |
644 | +body .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ |
645 | +body .sh { color: #219161 } /* Literal.String.Heredoc */ |
646 | +body .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ |
647 | +body .sx { color: #954121 } /* Literal.String.Other */ |
648 | +body .sr { color: #BB6688 } /* Literal.String.Regex */ |
649 | +body .s1 { color: #219161 } /* Literal.String.Single */ |
650 | +body .ss { color: #19469D } /* Literal.String.Symbol */ |
651 | +body .bp { color: #954121 } /* Name.Builtin.Pseudo */ |
652 | +body .vc { color: #19469D } /* Name.Variable.Class */ |
653 | +body .vg { color: #19469D } /* Name.Variable.Global */ |
654 | +body .vi { color: #19469D } /* Name.Variable.Instance */ |
655 | +body .il { color: #666666 } /* Literal.Number.Integer.Long */ |
656 | |
657 | === added file 'docs/pycco.css' |
658 | --- docs/pycco.css 1970-01-01 00:00:00 +0000 |
659 | +++ docs/pycco.css 2020-07-16 14:28:25 +0000 |
660 | @@ -0,0 +1,191 @@ |
661 | +/*--------------------- Layout and Typography ----------------------------*/ |
662 | +body { |
663 | + font-family: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif; |
664 | + font-size: 16px; |
665 | + line-height: 24px; |
666 | + color: #252519; |
667 | + margin: 0; padding: 0; |
668 | + background: #f5f5ff; |
669 | +} |
670 | +a { |
671 | + color: #261a3b; |
672 | +} |
673 | + a:visited { |
674 | + color: #261a3b; |
675 | + } |
676 | +p { |
677 | + margin: 0 0 15px 0; |
678 | +} |
679 | +h1, h2, h3, h4, h5, h6 { |
680 | + margin: 40px 0 15px 0; |
681 | +} |
682 | +h2, h3, h4, h5, h6 { |
683 | + margin-top: 0; |
684 | + } |
685 | +#container { |
686 | + background: white; |
687 | + } |
688 | +#container, div.section { |
689 | + position: relative; |
690 | +} |
691 | +#background { |
692 | + position: absolute; |
693 | + top: 0; left: 580px; right: 0; bottom: 0; |
694 | + background: #f5f5ff; |
695 | + border-left: 1px solid #e5e5ee; |
696 | + z-index: 0; |
697 | +} |
698 | +#jump_to, #jump_page { |
699 | + background: white; |
700 | + -webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777; |
701 | + -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px; |
702 | + font: 10px Arial; |
703 | + text-transform: uppercase; |
704 | + cursor: pointer; |
705 | + text-align: right; |
706 | +} |
707 | +#jump_to, #jump_wrapper { |
708 | + position: fixed; |
709 | + right: 0; top: 0; |
710 | + padding: 5px 10px; |
711 | +} |
712 | + #jump_wrapper { |
713 | + padding: 0; |
714 | + display: none; |
715 | + } |
716 | + #jump_to:hover #jump_wrapper { |
717 | + display: block; |
718 | + } |
719 | + #jump_page { |
720 | + padding: 5px 0 3px; |
721 | + margin: 0 0 25px 25px; |
722 | + } |
723 | + #jump_page .source { |
724 | + display: block; |
725 | + padding: 5px 10px; |
726 | + text-decoration: none; |
727 | + border-top: 1px solid #eee; |
728 | + } |
729 | + #jump_page .source:hover { |
730 | + background: #f5f5ff; |
731 | + } |
732 | + #jump_page .source:first-child { |
733 | + } |
734 | +div.docs { |
735 | + float: left; |
736 | + max-width: 500px; |
737 | + min-width: 500px; |
738 | + min-height: 5px; |
739 | + padding: 10px 25px 1px 50px; |
740 | + vertical-align: top; |
741 | + text-align: left; |
742 | +} |
743 | + .docs pre { |
744 | + margin: 15px 0 15px; |
745 | + padding-left: 15px; |
746 | + overflow-y: scroll; |
747 | + } |
748 | + .docs p tt, .docs p code { |
749 | + background: #f8f8ff; |
750 | + border: 1px solid #dedede; |
751 | + font-size: 12px; |
752 | + padding: 0 0.2em; |
753 | + } |
754 | + .octowrap { |
755 | + position: relative; |
756 | + } |
757 | + .octothorpe { |
758 | + font: 12px Arial; |
759 | + text-decoration: none; |
760 | + color: #454545; |
761 | + position: absolute; |
762 | + top: 3px; left: -20px; |
763 | + padding: 1px 2px; |
764 | + opacity: 0; |
765 | + -webkit-transition: opacity 0.2s linear; |
766 | + } |
767 | + div.docs:hover .octothorpe { |
768 | + opacity: 1; |
769 | + } |
770 | +div.code { |
771 | + margin-left: 580px; |
772 | + padding: 14px 15px 16px 50px; |
773 | + vertical-align: top; |
774 | +} |
775 | + .code pre, .docs p code { |
776 | + font-size: 12px; |
777 | + } |
778 | + pre, tt, code { |
779 | + line-height: 18px; |
780 | + font-family: Monaco, Consolas, "Lucida Console", monospace; |
781 | + margin: 0; padding: 0; |
782 | + } |
783 | +div.clearall { |
784 | + clear: both; |
785 | +} |
786 | + |
787 | + |
788 | +/*---------------------- Syntax Highlighting -----------------------------*/ |
789 | +td.linenos { background-color: #f0f0f0; padding-right: 10px; } |
790 | +span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; } |
791 | +body .hll { background-color: #ffffcc } |
792 | +body .c { color: #408080; font-style: italic } /* Comment */ |
793 | +body .err { border: 1px solid #FF0000 } /* Error */ |
794 | +body .k { color: #954121 } /* Keyword */ |
795 | +body .o { color: #666666 } /* Operator */ |
796 | +body .cm { color: #408080; font-style: italic } /* Comment.Multiline */ |
797 | +body .cp { color: #BC7A00 } /* Comment.Preproc */ |
798 | +body .c1 { color: #408080; font-style: italic } /* Comment.Single */ |
799 | +body .cs { color: #408080; font-style: italic } /* Comment.Special */ |
800 | +body .gd { color: #A00000 } /* Generic.Deleted */ |
801 | +body .ge { font-style: italic } /* Generic.Emph */ |
802 | +body .gr { color: #FF0000 } /* Generic.Error */ |
803 | +body .gh { color: #000080; font-weight: bold } /* Generic.Heading */ |
804 | +body .gi { color: #00A000 } /* Generic.Inserted */ |
805 | +body .go { color: #808080 } /* Generic.Output */ |
806 | +body .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ |
807 | +body .gs { font-weight: bold } /* Generic.Strong */ |
808 | +body .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ |
809 | +body .gt { color: #0040D0 } /* Generic.Traceback */ |
810 | +body .kc { color: #954121 } /* Keyword.Constant */ |
811 | +body .kd { color: #954121; font-weight: bold } /* Keyword.Declaration */ |
812 | +body .kn { color: #954121; font-weight: bold } /* Keyword.Namespace */ |
813 | +body .kp { color: #954121 } /* Keyword.Pseudo */ |
814 | +body .kr { color: #954121; font-weight: bold } /* Keyword.Reserved */ |
815 | +body .kt { color: #B00040 } /* Keyword.Type */ |
816 | +body .m { color: #666666 } /* Literal.Number */ |
817 | +body .s { color: #219161 } /* Literal.String */ |
818 | +body .na { color: #7D9029 } /* Name.Attribute */ |
819 | +body .nb { color: #954121 } /* Name.Builtin */ |
820 | +body .nc { color: #0000FF; font-weight: bold } /* Name.Class */ |
821 | +body .no { color: #880000 } /* Name.Constant */ |
822 | +body .nd { color: #AA22FF } /* Name.Decorator */ |
823 | +body .ni { color: #999999; font-weight: bold } /* Name.Entity */ |
824 | +body .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ |
825 | +body .nf { color: #0000FF } /* Name.Function */ |
826 | +body .nl { color: #A0A000 } /* Name.Label */ |
827 | +body .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ |
828 | +body .nt { color: #954121; font-weight: bold } /* Name.Tag */ |
829 | +body .nv { color: #19469D } /* Name.Variable */ |
830 | +body .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ |
831 | +body .w { color: #bbbbbb } /* Text.Whitespace */ |
832 | +body .mf { color: #666666 } /* Literal.Number.Float */ |
833 | +body .mh { color: #666666 } /* Literal.Number.Hex */ |
834 | +body .mi { color: #666666 } /* Literal.Number.Integer */ |
835 | +body .mo { color: #666666 } /* Literal.Number.Oct */ |
836 | +body .sb { color: #219161 } /* Literal.String.Backtick */ |
837 | +body .sc { color: #219161 } /* Literal.String.Char */ |
838 | +body .sd { color: #219161; font-style: italic } /* Literal.String.Doc */ |
839 | +body .s2 { color: #219161 } /* Literal.String.Double */ |
840 | +body .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ |
841 | +body .sh { color: #219161 } /* Literal.String.Heredoc */ |
842 | +body .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ |
843 | +body .sx { color: #954121 } /* Literal.String.Other */ |
844 | +body .sr { color: #BB6688 } /* Literal.String.Regex */ |
845 | +body .s1 { color: #219161 } /* Literal.String.Single */ |
846 | +body .ss { color: #19469D } /* Literal.String.Symbol */ |
847 | +body .bp { color: #954121 } /* Name.Builtin.Pseudo */ |
848 | +body .vc { color: #19469D } /* Name.Variable.Class */ |
849 | +body .vg { color: #19469D } /* Name.Variable.Global */ |
850 | +body .vi { color: #19469D } /* Name.Variable.Instance */ |
851 | +body .il { color: #666666 } /* Literal.Number.Integer.Long */ |
852 | |
853 | === modified file 'extras/__init__.py' |
854 | --- extras/__init__.py 2009-10-31 09:35:48 +0000 |
855 | +++ extras/__init__.py 2020-07-16 14:28:25 +0000 |
856 | @@ -18,13 +18,13 @@ |
857 | # along with this program; if not, write to the Free Software |
858 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
859 | |
860 | -from build_docs import build_docs |
861 | -from build_mo import build_mo |
862 | -from build_pot import build_pot |
863 | -from build_ui import build_ui |
864 | -from check_py24 import check_py24 |
865 | -from check_utf8 import check_utf8 |
866 | -from import_po import import_po |
867 | +from .build_docs import build_docs |
868 | +from .build_mo import build_mo |
869 | +from .build_pot import build_pot |
870 | +from .build_ui import build_ui |
871 | +from .check_py24 import check_py24 |
872 | +from .check_utf8 import check_utf8 |
873 | +from .import_po import import_po |
874 | |
875 | |
876 | cmdclass = { |
877 | |
878 | === modified file 'extras/build_mo.py' |
879 | --- extras/build_mo.py 2010-08-03 13:39:49 +0000 |
880 | +++ extras/build_mo.py 2020-07-16 14:28:25 +0000 |
881 | @@ -17,6 +17,7 @@ |
882 | # You should have received a copy of the GNU General Public License |
883 | # along with this program; if not, write to the Free Software |
884 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
885 | +# RJLRJL: breezy converted |
886 | |
887 | """build_mo command for setup.py""" |
888 | |
889 | @@ -28,7 +29,7 @@ |
890 | import os |
891 | import re |
892 | |
893 | -from en_po import regenerate_en |
894 | +from .en_po import regenerate_en |
895 | |
896 | |
897 | class build_mo(Command): |
898 | @@ -44,8 +45,7 @@ |
899 | ('output-base=', 'o', 'mo-files base name'), |
900 | ('source-dir=', None, 'Directory with sources po files'), |
901 | ('force', 'f', 'Force creation of mo files'), |
902 | - ('lang=', None, 'Comma-separated list of languages ' |
903 | - 'to process'), |
904 | + ('lang=', None, 'Comma-separated list of languages to process'), |
905 | ] |
906 | |
907 | boolean_options = ['force'] |
908 | @@ -89,14 +89,15 @@ |
909 | log.warn("Skip compiling po files.") |
910 | return |
911 | |
912 | - if 'en' in self.lang: |
913 | - if find_executable('msginit') is None: |
914 | - log.warn("GNU gettext msginit utility not found!") |
915 | - log.warn("Skip creating English PO file.") |
916 | - else: |
917 | - log.info('Creating English PO file...') |
918 | - pot = (self.prj_name or 'messages') + '.pot' |
919 | - regenerate_en(self.prj_name, self.source_dir, pot, self.spawn) |
920 | + # RJLRJL: TODO: by-passed for now: we don't want to shred what we have |
921 | + # if 'en' in self.lang: |
922 | + # if find_executable('msginit') is None: |
923 | + # log.warn("GNU gettext msginit utility not found!") |
924 | + # log.warn("Skip creating English PO file.") |
925 | + # else: |
926 | + # log.info('Creating English PO file...') |
927 | + # pot = (self.prj_name or 'messages') + '.pot' |
928 | + # regenerate_en(self.prj_name, self.source_dir, pot, self.spawn) |
929 | |
930 | basename = self.output_base |
931 | if not basename.endswith('.mo'): |
932 | |
933 | === modified file 'extras/build_pot.py' |
934 | --- extras/build_pot.py 2011-08-03 06:03:19 +0000 |
935 | +++ extras/build_pot.py 2020-07-16 14:28:25 +0000 |
936 | @@ -25,7 +25,7 @@ |
937 | from distutils.core import Command |
938 | from distutils.errors import DistutilsOptionError |
939 | |
940 | -from en_po import regenerate_en |
941 | +from .en_po import regenerate_en |
942 | |
943 | |
944 | class build_pot(Command): |
945 | @@ -39,8 +39,7 @@ |
946 | # - help string. |
947 | user_options = [('build-dir=', 'd', 'Directory to put POT file'), |
948 | ('output=', 'o', 'POT filename'), |
949 | - ('lang=', None, 'Comma-separated list of languages ' |
950 | - 'to update po-files'), |
951 | + ('lang=', None, 'Comma-separated list of languages to update po-files'), |
952 | ('no-lang', 'N', "Don't update po-files"), |
953 | ('english', 'E', 'Regenerate English PO file'), |
954 | ] |
955 | @@ -57,12 +56,11 @@ |
956 | if self.build_dir is None: |
957 | self.build_dir = 'po' |
958 | if not self.output: |
959 | - self.output = (self.distribution.get_name() or 'messages')+'.pot' |
960 | + self.output = (self.distribution.get_name() or 'messages')+ '.pot' |
961 | if self.lang is not None: |
962 | self.lang = [i.strip() for i in self.lang.split(',') if i.strip()] |
963 | if self.lang and self.no_lang: |
964 | - raise DistutilsOptionError("You can't use options " |
965 | - "--lang=XXX and --no-lang in the same time.") |
966 | + raise DistutilsOptionError("You can't use options --lang=XXX and --no-lang in the same time.") |
967 | |
968 | def _force_LF(self, src, dst=None): |
969 | f = open(src, 'rU') |
970 | @@ -93,27 +91,35 @@ |
971 | if not os.path.isdir(self.build_dir): |
972 | log.info('Make directory: ' + self.build_dir) |
973 | os.makedirs(self.build_dir) |
974 | - self.spawn(['xgettext', |
975 | - '--keyword=N_', |
976 | - '-p', self.build_dir, |
977 | - '-o', self.output, |
978 | - '__init__.py', |
979 | - ] |
980 | - + glob.glob('lib/*.py') |
981 | - + glob.glob('lib/widgets/*.py') |
982 | - ) |
983 | - self._force_LF(fullname) |
984 | + |
985 | + |
986 | + # RJLRJL: TODO: bypassed for now, to not shred what we have |
987 | + # self.spawn(['xgettext', |
988 | + # '--keyword=N_', |
989 | + # '-p', self.build_dir, |
990 | + # '-o', self.output, |
991 | + # '__init__.py', |
992 | + # ] + glob.glob('lib/*.py') + glob.glob('lib/widgets/*.py') |
993 | + # ) |
994 | + # self._force_LF(fullname) |
995 | + |
996 | # regenerate english PO |
997 | + print('self.english is ', self.english, 'project is ', prj_name) |
998 | if self.english: |
999 | log.info('Regenerating English PO file...') |
1000 | + log.info(' project: {0}, build_dir {1}, output {2}'.format(prj_name, self.build_dir, self.output)) |
1001 | + print('Regenerating English PO file...') |
1002 | + print(' project: {0}, build_dir {1}, output {2}'.format(prj_name, self.build_dir, self.output)) |
1003 | regenerate_en(prj_name, self.build_dir, self.output, self.spawn) |
1004 | # search and update all po-files |
1005 | if self.no_lang: |
1006 | + print('No language: stopping') |
1007 | return |
1008 | for po in glob.glob(os.path.join(self.build_dir,'*.po')): |
1009 | + print('\tworking on ', po) |
1010 | if self.lang is not None: |
1011 | po_lang = os.path.splitext(os.path.basename(po))[0] |
1012 | - if prj_name and po_lang.startswith(prj_name+'-'): |
1013 | + if prj_name and po_lang.startswith(prj_name + '-'): |
1014 | po_lang = po_lang[5:] |
1015 | if po_lang not in self.lang: |
1016 | continue |
1017 | |
1018 | === modified file 'extras/build_ui.py' |
1019 | --- extras/build_ui.py 2017-09-11 06:53:22 +0000 |
1020 | +++ extras/build_ui.py 2020-07-16 14:28:25 +0000 |
1021 | @@ -21,7 +21,7 @@ |
1022 | from distutils import log |
1023 | from distutils.core import Command |
1024 | from distutils.dep_util import newer |
1025 | -from StringIO import StringIO |
1026 | +from io import StringIO |
1027 | import glob |
1028 | import os |
1029 | import re |
1030 | @@ -65,6 +65,7 @@ |
1031 | source = source.replace("from PyQt4 import QtCore, QtGui", |
1032 | "from PyQt4 import QtCore, QtGui\n" |
1033 | "from breezy.plugins.%s.lib.i18n import gettext\n" % prj_name) |
1034 | - f = open(pyfile, "wb") |
1035 | + # f = open(pyfile, "wb") |
1036 | + f = open(pyfile, "w") |
1037 | f.write(source) |
1038 | f.close() |
1039 | |
1040 | === modified file 'extras/check_py24.py' |
1041 | --- extras/check_py24.py 2009-02-27 12:42:38 +0000 |
1042 | +++ extras/check_py24.py 2020-07-16 14:28:25 +0000 |
1043 | @@ -58,7 +58,7 @@ |
1044 | f.close() |
1045 | try: |
1046 | compile(content, fullname, 'exec') |
1047 | - except SyntaxError, e: |
1048 | + except SyntaxError as e: |
1049 | log.error(str(e)) |
1050 | if self.verbose: |
1051 | traceback.print_exc(0) |
1052 | |
1053 | === modified file 'extras/check_utf8.py' |
1054 | --- extras/check_utf8.py 2009-02-02 03:09:46 +0000 |
1055 | +++ extras/check_utf8.py 2020-07-16 14:28:25 +0000 |
1056 | @@ -54,7 +54,7 @@ |
1057 | f.close() |
1058 | try: |
1059 | content.decode('utf-8') |
1060 | - except UnicodeDecodeError, e: |
1061 | + except UnicodeDecodeError as e: |
1062 | log.error(fullname + ': ' + str(e)) |
1063 | # skip some directories |
1064 | for dname in dirs[:]: |
1065 | |
1066 | === modified file 'extras/en_po.py' |
1067 | --- extras/en_po.py 2010-08-03 13:39:49 +0000 |
1068 | +++ extras/en_po.py 2020-07-16 14:28:25 +0000 |
1069 | @@ -28,12 +28,7 @@ |
1070 | else: |
1071 | en_po = 'en.po' |
1072 | en_po_path = os.path.join(po_dir, en_po) |
1073 | - spawn(['msginit', |
1074 | - '--no-translator', |
1075 | - '-l', 'en', |
1076 | - '-i', os.path.join(po_dir, pot_file), |
1077 | - '-o', en_po_path, |
1078 | - ]) |
1079 | + spawn(['msginit', '--no-translator', '-l', 'en', '-i', os.path.join(po_dir, pot_file), '-o', en_po_path, ]) |
1080 | # normalize line-endings in en.po file (to LF) |
1081 | f = open(en_po_path, 'rU') |
1082 | s = f.read() |
1083 | |
1084 | === modified file 'extras/import_po.py' |
1085 | --- extras/import_po.py 2010-08-03 13:39:49 +0000 |
1086 | +++ extras/import_po.py 2020-07-16 14:28:25 +0000 |
1087 | @@ -23,7 +23,7 @@ |
1088 | from distutils.core import Command |
1089 | from distutils.spawn import find_executable |
1090 | |
1091 | -from en_po import regenerate_en |
1092 | +from .en_po import regenerate_en |
1093 | |
1094 | |
1095 | class import_po(Command): |
1096 | |
1097 | === renamed file 'installer/qbzr-setup.iss' => 'installer/qbrz-setup.iss' |
1098 | --- installer/qbzr-setup.iss 2013-10-15 10:11:40 +0000 |
1099 | +++ installer/qbrz-setup.iss 2020-07-16 14:28:25 +0000 |
1100 | @@ -5,17 +5,17 @@ |
1101 | ; NOTE: The value of AppId uniquely identifies this application. |
1102 | ; Do not use the same AppId value in installers for other applications. |
1103 | ; (To generate a new GUID, click Tools | Generate GUID inside the IDE.) |
1104 | -AppId=QBzr |
1105 | +AppId=QBrz |
1106 | |
1107 | -AppName= QBzr |
1108 | -AppVerName= QBzr 0.23.2 |
1109 | -OutputBaseFilename=qbzr-setup-0.23.2 |
1110 | +AppName= QBrz |
1111 | +AppVerName= QBrz 0.3.1 |
1112 | +OutputBaseFilename=qbrz-setup-0.3.1 |
1113 | |
1114 | SourceDir="..\" |
1115 | OutputDir="." |
1116 | -OutputManifestFile=qbzr-setup-iss.log |
1117 | +OutputManifestFile=qbrz-setup-iss.log |
1118 | |
1119 | -AppPublisher=QBzr Developers |
1120 | +AppPublisher=QBrz Developers |
1121 | AppPublisherURL=http://launchpad.net/qbzr |
1122 | AppSupportURL=http://groups.google.com/group/qbzr |
1123 | AppUpdatesURL=http://launchpad.net/qbzr/+download |
1124 | @@ -70,26 +70,26 @@ |
1125 | Type: files; Name: {app}\lib\widgets\*.pyo |
1126 | |
1127 | [Registry] |
1128 | -Root: HKLM; Subkey: "Software\QBzr"; Flags: uninsdeletekey |
1129 | -Root: HKLM; Subkey: "Software\QBzr"; ValueType: string; ValueName: "InstallPath"; ValueData: "{app}" |
1130 | +Root: HKLM; Subkey: "Software\QBrz"; Flags: uninsdeletekey |
1131 | +Root: HKLM; Subkey: "Software\QBrz"; ValueType: string; ValueName: "InstallPath"; ValueData: "{app}" |
1132 | |
1133 | [Code] |
1134 | -{Function detects system-wide installation of bzr: either bzr.exe or python-based} |
1135 | -function GetBzrPath(): String; |
1136 | +{Function detects system-wide installation of brz: either brz.exe or python-based} |
1137 | +function GetBrzPath(): String; |
1138 | var |
1139 | - BzrPath: String; |
1140 | + BrzPath: String; |
1141 | PythonVersions: TArrayOfString; |
1142 | Ix: Integer; |
1143 | PythonKey: String; |
1144 | PythonPath: String; |
1145 | - BzrlibPath: String; |
1146 | + BrzlibPath: String; |
1147 | Path: String; |
1148 | begin |
1149 | - {Check bzr.exe presence} |
1150 | - if RegQueryStringValue(HKEY_LOCAL_MACHINE, 'Software\Bazaar', 'InstallPath', BzrPath) then begin |
1151 | - Result := BzrPath; |
1152 | + {Check brz.exe presence} |
1153 | + if RegQueryStringValue(HKEY_LOCAL_MACHINE, 'Software\Breezy', 'InstallPath', BrzPath) then begin |
1154 | + Result := BrzPath; |
1155 | end else begin |
1156 | - BzrlibPath := ''; |
1157 | + BrzlibPath := ''; |
1158 | {Get list of all installed python versions} |
1159 | if RegGetSubkeyNames(HKEY_LOCAL_MACHINE, 'Software\Python\PythonCore', PythonVersions) then begin |
1160 | {Iterate over installed pythons and check if there is installed bzrlib} |
1161 | @@ -98,39 +98,39 @@ |
1162 | if RegQueryStringValue(HKEY_LOCAL_MACHINE, PythonKey, '', PythonPath) then begin |
1163 | Path := AddBackslash(PythonPath) + 'Lib\site-packages\bzrlib' |
1164 | if DirExists(Path) then begin |
1165 | - BzrlibPath := Path; |
1166 | + BrzlibPath := Path; |
1167 | break; |
1168 | end; |
1169 | end; |
1170 | end; |
1171 | end; |
1172 | - Result := BzrlibPath; |
1173 | + Result := BrzlibPath; |
1174 | end; |
1175 | end; |
1176 | |
1177 | -{Function determines best possible PATH to install QBzr. |
1178 | - At first it tries to find system-wide installation (either bzr.exe or python-based) |
1179 | - then checks BZR_PLUGIN_PATH, |
1180 | - if all above fails then it suggests install to %APPDATA%\bazaar\2.0 |
1181 | +{Function determines best possible PATH to install QBrz. |
1182 | + At first it tries to find system-wide installation (either brz.exe or python-based) |
1183 | + then checks BRZ_PLUGIN_PATH, |
1184 | + if all above fails then it suggests install to %APPDATA%\Breezy\2.0 |
1185 | } |
1186 | function GetDirName(Param: String): String; |
1187 | var |
1188 | Path: String; |
1189 | - BzrPath: String; |
1190 | - EnvBzrPluginPath: String; |
1191 | + BrzPath: String; |
1192 | + EnvBrzPluginPath: String; |
1193 | Ix: Integer; |
1194 | begin |
1195 | - Path := ExpandConstant('{userappdata}\bazaar\2.0\plugins\qbzr'); |
1196 | - BzrPath := GetBzrPath(); |
1197 | - if BzrPath <> '' then begin |
1198 | - Path := AddBackslash(BzrPath) + 'plugins\qbzr'; |
1199 | + Path := ExpandConstant('{userappdata}\Breezy\2.0\plugins\qbzr'); |
1200 | + BrzPath := GetBrzPath(); |
1201 | + if BrzPath <> '' then begin |
1202 | + Path := AddBackslash(BrzPath) + 'plugins\qbzr'; |
1203 | end else begin |
1204 | - EnvBzrPluginPath := GetEnv('BZR_PLUGIN_PATH') |
1205 | - Ix := Pos(';', EnvBzrPluginPath) |
1206 | + EnvBrzPluginPath := GetEnv('BRZ_PLUGIN_PATH') |
1207 | + Ix := Pos(';', EnvBrzPluginPath) |
1208 | if Ix > 0 then |
1209 | - EnvBzrPluginPath := Copy(EnvBzrPluginPath, 1, Ix-1) |
1210 | - if EnvBzrPluginPath <> '' then |
1211 | - Path := AddBackslash(EnvBzrPluginPath) + 'qbzr'; |
1212 | + EnvBrzPluginPath := Copy(EnvBrzPluginPath, 1, Ix-1) |
1213 | + if EnvBrzPluginPath <> '' then |
1214 | + Path := AddBackslash(EnvBrzPluginPath) + 'qbzr'; |
1215 | end; |
1216 | Result := Path; |
1217 | end; |
1218 | |
1219 | === added file 'iscc' |
1220 | --- iscc 1970-01-01 00:00:00 +0000 |
1221 | +++ iscc 2020-07-16 14:28:25 +0000 |
1222 | @@ -0,0 +1,5 @@ |
1223 | +#!/bin/sh |
1224 | +unset DISPLAY |
1225 | +scriptname=$1 |
1226 | +[ -f "$scriptname" ] && scriptname=$(winepath -w "$scriptname") |
1227 | +wine "C:\Program Files (x86)\Inno Setup 5\ISCC.exe" "$scriptname" "$2" "$3" "$4" "$5" "$6" "$7" "$8" "$9" |
1228 | |
1229 | === modified file 'lib/__init__.py' |
1230 | --- lib/__init__.py 2012-02-19 23:50:27 +0000 |
1231 | +++ lib/__init__.py 2020-07-16 14:28:25 +0000 |
1232 | @@ -1,4 +1,6 @@ |
1233 | -# -*- coding: utf-8 -*- |
1234 | +#!/usr/bin/python3 -bb |
1235 | +# # -*- coding: utf-8 -*- |
1236 | + |
1237 | # |
1238 | # QBzr - Qt frontend to Bazaar commands |
1239 | # Copyright (C) 2006-2008 Lukáš Lalinský <lalinsky@gmail.com> |
1240 | @@ -34,9 +36,9 @@ |
1241 | return True |
1242 | return False |
1243 | |
1244 | - import __builtin__ |
1245 | - __builtin__.all = _all_2_4_compat |
1246 | - __builtin__.any = _any_2_4_compat |
1247 | + import builtins |
1248 | + builtins.all = _all_2_4_compat |
1249 | + builtins.any = _any_2_4_compat |
1250 | |
1251 | # Special constant |
1252 | MS_WINDOWS = (sys.platform == 'win32') |
1253 | |
1254 | === modified file 'lib/add.py' |
1255 | --- lib/add.py 2017-09-11 06:53:22 +0000 |
1256 | +++ lib/add.py 2020-07-16 14:28:25 +0000 |
1257 | @@ -40,79 +40,71 @@ |
1258 | def __init__(self, tree, selected_list, dialog=True, ui_mode=True, parent=None, local=None, message=None): |
1259 | self.tree = tree |
1260 | self.initial_selected_list = selected_list |
1261 | - |
1262 | + # print('*^*^*^^ tree is', self.tree, 'initial_selected', selected_list) |
1263 | + |
1264 | super(AddWindow, self).__init__( |
1265 | - gettext("Add"), |
1266 | - name = "add", |
1267 | - default_size = (400, 400), |
1268 | - ui_mode = ui_mode, |
1269 | - dialog = dialog, |
1270 | - parent = parent, |
1271 | - hide_progress=True, |
1272 | - ) |
1273 | - |
1274 | + gettext("Add"), |
1275 | + name = "add", |
1276 | + default_size = (400, 400), |
1277 | + ui_mode = ui_mode, |
1278 | + dialog = dialog, |
1279 | + parent = parent, |
1280 | + hide_progress=True, |
1281 | + ) |
1282 | + |
1283 | self.throbber = ThrobberWidget(self) |
1284 | |
1285 | # Display the list of unversioned files |
1286 | groupbox = QtGui.QGroupBox(gettext("Unversioned Files"), self) |
1287 | vbox = QtGui.QVBoxLayout(groupbox) |
1288 | |
1289 | - self.filelist = TreeWidget(groupbox) |
1290 | - self.filelist.throbber = self.throbber |
1291 | - self.filelist.tree_model.is_item_in_select_all = lambda item: ( |
1292 | + self.filelist_widget = TreeWidget(groupbox) |
1293 | + self.filelist_widget.throbber = self.throbber |
1294 | + |
1295 | + self.filelist_widget.tree_model.is_item_in_select_all = lambda item: ( |
1296 | # Is in select all. - Not versioned, and not Ignored |
1297 | - item.change is not None and |
1298 | - item.change.is_ignored() is None and |
1299 | - not item.change.is_versioned(), |
1300 | - |
1301 | + item.change is not None and item.change.is_ignored() is None and not item.change.is_versioned(), |
1302 | # look at children. - Not ignored |
1303 | - item.change is not None and item.change.is_ignored() is None or |
1304 | - item.change is None |
1305 | + item.change is not None and item.change.is_ignored() is None or item.change is None |
1306 | ) |
1307 | - |
1308 | + |
1309 | def filter_context_menu(): |
1310 | - items = self.filelist.get_selection_items() |
1311 | + items = self.filelist_widget.get_selection_items() |
1312 | selection_len = len(items) |
1313 | single_file = (selection_len == 1 and items[0].item.kind == "file") |
1314 | - single_item_in_tree = (selection_len == 1 and |
1315 | - (items[0].change is None or items[0].change[6][1] is not None)) |
1316 | - |
1317 | - self.filelist.action_open_file.setEnabled(True) |
1318 | - self.filelist.action_open_file.setVisible(True) |
1319 | - self.filelist.action_show_file.setEnabled(single_file) |
1320 | - self.filelist.action_show_file.setVisible(True) |
1321 | - self.filelist.action_show_annotate.setVisible(False) |
1322 | - self.filelist.action_show_log.setVisible(False) |
1323 | - self.filelist.action_show_diff.setVisible(False) |
1324 | - self.filelist.action_add.setVisible(False) |
1325 | - self.filelist.action_revert.setVisible(False) |
1326 | - self.filelist.action_merge.setVisible(False) |
1327 | - self.filelist.action_resolve.setVisible(False) |
1328 | - self.filelist.action_rename.setVisible(True) |
1329 | - self.filelist.action_rename.setEnabled(single_item_in_tree) |
1330 | - self.filelist.action_remove.setVisible(False) |
1331 | - self.filelist.action_mark_move.setVisible(False) |
1332 | - |
1333 | - self.filelist.filter_context_menu = filter_context_menu |
1334 | - |
1335 | - vbox.addWidget(self.filelist) |
1336 | - |
1337 | - selectall_checkbox = SelectAllCheckBox(self.filelist, groupbox) |
1338 | + single_item_in_tree = (selection_len == 1 and (items[0].change is None or items[0].change[6][1] is not None)) |
1339 | + |
1340 | + self.filelist_widget.action_open_file.setEnabled(True) |
1341 | + self.filelist_widget.action_open_file.setVisible(True) |
1342 | + self.filelist_widget.action_show_file.setEnabled(single_file) |
1343 | + self.filelist_widget.action_show_file.setVisible(True) |
1344 | + self.filelist_widget.action_show_annotate.setVisible(False) |
1345 | + self.filelist_widget.action_show_log.setVisible(False) |
1346 | + self.filelist_widget.action_show_diff.setVisible(False) |
1347 | + self.filelist_widget.action_add.setVisible(False) |
1348 | + self.filelist_widget.action_revert.setVisible(False) |
1349 | + self.filelist_widget.action_merge.setVisible(False) |
1350 | + self.filelist_widget.action_resolve.setVisible(False) |
1351 | + self.filelist_widget.action_rename.setVisible(True) |
1352 | + self.filelist_widget.action_rename.setEnabled(single_item_in_tree) |
1353 | + self.filelist_widget.action_remove.setVisible(False) |
1354 | + self.filelist_widget.action_mark_move.setVisible(False) |
1355 | + |
1356 | + self.filelist_widget.filter_context_menu = filter_context_menu |
1357 | + |
1358 | + vbox.addWidget(self.filelist_widget) |
1359 | + |
1360 | + selectall_checkbox = SelectAllCheckBox(self.filelist_widget, groupbox) |
1361 | vbox.addWidget(selectall_checkbox) |
1362 | selectall_checkbox.setCheckState(QtCore.Qt.Checked) |
1363 | selectall_checkbox.setEnabled(True) |
1364 | |
1365 | - self.show_ignored_checkbox = QtGui.QCheckBox( |
1366 | - gettext("Show ignored files"), |
1367 | - groupbox) |
1368 | + self.show_ignored_checkbox = QtGui.QCheckBox(gettext("Show ignored files"), groupbox) |
1369 | vbox.addWidget(self.show_ignored_checkbox) |
1370 | self.connect(self.show_ignored_checkbox, QtCore.SIGNAL("toggled(bool)"), self.show_ignored) |
1371 | - |
1372 | + |
1373 | # groupbox gets disabled as we are executing. |
1374 | - QtCore.QObject.connect(self, |
1375 | - QtCore.SIGNAL("disableUi(bool)"), |
1376 | - groupbox, |
1377 | - QtCore.SLOT("setDisabled(bool)")) |
1378 | + QtCore.QObject.connect(self, QtCore.SIGNAL("disableUi(bool)"), groupbox, QtCore.SLOT("setDisabled(bool)")) |
1379 | |
1380 | self.splitter = QtGui.QSplitter(QtCore.Qt.Vertical) |
1381 | self.splitter.addWidget(groupbox) |
1382 | @@ -134,17 +126,21 @@ |
1383 | @ui_current_widget |
1384 | @reports_exception() |
1385 | def initial_load(self): |
1386 | - self.filelist.tree_model.checkable = True |
1387 | - fmodel = self.filelist.tree_filter_model |
1388 | + # print('*** initial_load called') |
1389 | + self.filelist_widget.tree_model.checkable = True |
1390 | + fmodel = self.filelist_widget.tree_filter_model |
1391 | fmodel.setFilter(fmodel.CHANGED, False) |
1392 | fmodel.setFilter(fmodel.UNCHANGED, False) |
1393 | - self.filelist.set_tree(self.tree, changes_mode = True, |
1394 | + self.filelist_widget.set_tree(self.tree, changes_mode = True, |
1395 | initial_checked_paths=self.initial_selected_list, |
1396 | change_load_filter=lambda c:not c.is_versioned()) |
1397 | self.throbber.hide() |
1398 | + # print('leaving initial_load ***') |
1399 | |
1400 | def _get_files_to_add(self): |
1401 | - return [ref.path for ref in self.filelist.tree_model.iter_checked()] |
1402 | + # print('==== getting files ====') |
1403 | + # OK pressed |
1404 | + return [ref.path for ref in self.filelist_widget.tree_model.iter_checked()] |
1405 | |
1406 | def validate(self): |
1407 | if not self._get_files_to_add(): |
1408 | @@ -154,15 +150,16 @@ |
1409 | |
1410 | def do_start(self): |
1411 | """Add the files.""" |
1412 | + # print('\tdo_start entry') |
1413 | files = self._get_files_to_add() |
1414 | - self.process_widget.do_start(self.tree.basedir, "add", "--no-recurse", |
1415 | - *files) |
1416 | + self.process_widget.do_start(self.tree.basedir, "add", "--no-recurse", *files) |
1417 | + # print('\tdo_start EXIT') |
1418 | |
1419 | def show_ignored(self, state): |
1420 | """Show/hide ignored files.""" |
1421 | - fmodel = self.filelist.tree_filter_model |
1422 | + fmodel = self.filelist_widget.tree_filter_model |
1423 | fmodel.setFilter(fmodel.IGNORED, state) |
1424 | - #self.filelist.update_selectall_state(None, None) |
1425 | + # self.filelist_widget.update_selectall_state(None, None) |
1426 | |
1427 | def _saveSize(self, config): |
1428 | SubProcessDialog._saveSize(self, config) |
1429 | |
1430 | === modified file 'lib/annotate.py' |
1431 | --- lib/annotate.py 2017-11-13 23:31:28 +0000 |
1432 | +++ lib/annotate.py 2020-07-16 14:28:25 +0000 |
1433 | @@ -64,23 +64,23 @@ |
1434 | from breezy.plugins.qbrz.lib.revtreeview import paint_revno, get_text_color |
1435 | from breezy.plugins.qbrz.lib import logmodel |
1436 | from breezy.plugins.qbrz.lib.loggraphviz import BranchInfo |
1437 | -from breezy.patiencediff import PatienceSequenceMatcher as SequenceMatcher |
1438 | +from patiencediff import PatienceSequenceMatcher as SequenceMatcher |
1439 | ''') |
1440 | |
1441 | class AnnotateBar(AnnotateBarBase): |
1442 | - |
1443 | + |
1444 | def __init__(self, edit, parent, get_revno): |
1445 | super(AnnotateBar, self).__init__(edit, parent) |
1446 | - |
1447 | + |
1448 | self.get_revno = get_revno |
1449 | self.annotate = None |
1450 | self.rev_colors = {} |
1451 | self._highlight_revids = set() |
1452 | self.highlight_lines = [] |
1453 | - |
1454 | + |
1455 | self.splitter = None |
1456 | self.adjustWidth(1, 999) |
1457 | - |
1458 | + |
1459 | self.connect(edit, |
1460 | QtCore.SIGNAL("cursorPositionChanged()"), |
1461 | self.edit_cursorPositionChanged) |
1462 | @@ -118,22 +118,22 @@ |
1463 | fm = self.fontMetrics() |
1464 | text_margin = self.style().pixelMetric( |
1465 | QtGui.QStyle.PM_FocusFrameHMargin, None, self) + 1 |
1466 | - |
1467 | - self.line_number_width = fm.width(unicode(lines)) |
1468 | + |
1469 | + self.line_number_width = fm.width(str(lines)) |
1470 | self.line_number_width += (text_margin * 2) |
1471 | - |
1472 | - self.revno_width = fm.width(unicode(max_revno)+".8.88") |
1473 | - self.max_mainline_digits = len(unicode(max_revno)) |
1474 | + |
1475 | + self.revno_width = fm.width(str(max_revno)+".8.88") |
1476 | + self.max_mainline_digits = len(str(max_revno)) |
1477 | self.revno_width += (text_margin * 2) |
1478 | - |
1479 | + |
1480 | if self.splitter: |
1481 | if 0: self.splitter = QtGui.QSplitter |
1482 | width = (self.line_number_width + self.revno_width + |
1483 | fm.width("Joe I have a Long Name")) |
1484 | self.splitter.setSizes([width, 1000]) |
1485 | - |
1486 | + |
1487 | self.setMinimumWidth(self.line_number_width + self.revno_width) |
1488 | - |
1489 | + |
1490 | def paint_line(self, painter, rect, line_number, is_current): |
1491 | fm = self.fontMetrics() |
1492 | painter.save() |
1493 | @@ -146,26 +146,26 @@ |
1494 | painter.fillRect(rect, QtGui.QBrush(option.palette.highlight())) |
1495 | style.drawPrimitive(QtGui.QStyle.PE_PanelItemViewItem, |
1496 | option, painter, self) |
1497 | - |
1498 | + |
1499 | painter.setPen(get_text_color(option, style)) |
1500 | elif self.annotate and line_number-1 < len(self.annotate): |
1501 | revid, is_top = self.annotate[line_number - 1] |
1502 | if revid in self.rev_colors: |
1503 | painter.fillRect(rect, self.rev_colors[revid]) |
1504 | - |
1505 | + |
1506 | text_margin = self.style().pixelMetric( |
1507 | QtGui.QStyle.PM_FocusFrameHMargin, None, self) + 1 |
1508 | - |
1509 | + |
1510 | if 0: rect = QtCore.QRect |
1511 | line_number_rect = QtCore.QRect( |
1512 | rect.left() + text_margin, |
1513 | rect.top(), |
1514 | self.line_number_width - (2 * text_margin), |
1515 | rect.height()) |
1516 | - |
1517 | + |
1518 | painter.drawText(line_number_rect, QtCore.Qt.AlignRight, |
1519 | - unicode(line_number)) |
1520 | - |
1521 | + str(line_number)) |
1522 | + |
1523 | if self.annotate and line_number-1 < len(self.annotate): |
1524 | revid, is_top = self.annotate[line_number - 1] |
1525 | if is_top: |
1526 | @@ -173,16 +173,16 @@ |
1527 | font = painter.font() |
1528 | font.setBold(True) |
1529 | painter.setFont(font) |
1530 | - |
1531 | + |
1532 | revno_rect = QtCore.QRect( |
1533 | rect.left() + self.line_number_width + text_margin, |
1534 | rect.top(), |
1535 | self.revno_width - (2 * text_margin), |
1536 | rect.height()) |
1537 | paint_revno(painter, revno_rect, |
1538 | - QtCore.QString(self.get_revno(revid)), |
1539 | + str(self.get_revno(revid)), |
1540 | self.max_mainline_digits) |
1541 | - |
1542 | + |
1543 | if revid in cached_revisions: |
1544 | rev = cached_revisions[revid] |
1545 | author_rect = QtCore.QRect( |
1546 | @@ -191,10 +191,10 @@ |
1547 | rect.top(), |
1548 | rect.right() - revno_rect.right() - (2 * text_margin), |
1549 | rect.height()) |
1550 | - author = QtCore.QString(get_apparent_author_name(rev)) |
1551 | + author = get_apparent_author_name(rev) |
1552 | if fm.width(author) > author_rect.width(): |
1553 | author= fm.elidedText(author, QtCore.Qt.ElideRight, |
1554 | - author_rect.width()) |
1555 | + author_rect.width()) |
1556 | painter.drawText(author_rect, 0, author) |
1557 | painter.restore() |
1558 | |
1559 | @@ -208,7 +208,7 @@ |
1560 | block = self.firstVisibleBlock() |
1561 | painter = QtGui.QPainter(self.viewport()) |
1562 | painter.setClipRect(event.rect()) |
1563 | - |
1564 | + |
1565 | line_count = block.blockNumber() |
1566 | # Iterate over all visible text blocks in the document. |
1567 | while block.isValid(): |
1568 | @@ -217,21 +217,21 @@ |
1569 | # area. |
1570 | rect = self.blockBoundingGeometry(block) |
1571 | rect = rect.translated(self.contentOffset()) |
1572 | - |
1573 | + |
1574 | if not block.isVisible() or rect.top() >= event.rect().bottom(): |
1575 | break |
1576 | - |
1577 | + |
1578 | if line_count - 1 >= len(self.annotate): |
1579 | break |
1580 | - |
1581 | + |
1582 | revid, is_top = self.annotate[line_count - 1] |
1583 | if revid in self.rev_colors: |
1584 | painter.fillRect(rect, self.rev_colors[revid]) |
1585 | - |
1586 | + |
1587 | block = block.next() |
1588 | del painter |
1589 | QtGui.QPlainTextEdit.paintEvent(self, event) |
1590 | - |
1591 | + |
1592 | def get_positions(self): |
1593 | """Returns the charator positons for the selection start, |
1594 | selection end, center of the viewport, an the number of lines from |
1595 | @@ -240,11 +240,11 @@ |
1596 | old_center = self.cursorForPosition(QtCore.QPoint(0, self.height() / 2)) |
1597 | lines_to_center = (old_center.block().blockNumber() - |
1598 | self.verticalScrollBar().value()) |
1599 | - |
1600 | + |
1601 | return (old_cursor.selectionStart(), |
1602 | old_cursor.selectionEnd(), |
1603 | old_center.position()) , lines_to_center |
1604 | - |
1605 | + |
1606 | def set_positions(self, new_positions, lines_to_center): |
1607 | new_start, new_end, new_center = new_positions |
1608 | if new_center: |
1609 | @@ -252,7 +252,7 @@ |
1610 | new_center_cursor.setPosition(new_center) |
1611 | new_scroll = new_center_cursor.block().blockNumber() - lines_to_center |
1612 | self.verticalScrollBar().setValue(new_scroll) |
1613 | - |
1614 | + |
1615 | new_selection_cursor = QtGui.QTextCursor(self.document()) |
1616 | new_selection_cursor.movePosition(QtGui.QTextCursor.Right, |
1617 | QtGui.QTextCursor.MoveAnchor, |
1618 | @@ -260,7 +260,7 @@ |
1619 | new_selection_cursor.movePosition(QtGui.QTextCursor.Right, |
1620 | QtGui.QTextCursor.KeepAnchor, |
1621 | new_end - new_start) |
1622 | - self.setTextCursor(new_selection_cursor) |
1623 | + self.setTextCursor(new_selection_cursor) |
1624 | |
1625 | |
1626 | class AnnotateWindow(QBzrWindow): |
1627 | @@ -280,13 +280,13 @@ |
1628 | self.branch = branch |
1629 | self.annotate_tree = annotate_tree |
1630 | self.working_tree = working_tree |
1631 | - if (self.working_tree is None and |
1632 | + if (self.working_tree is None and |
1633 | isinstance(annotate_tree, WorkingTree)): |
1634 | self.working_tree = annotate_tree |
1635 | - |
1636 | + |
1637 | self.no_graph = no_graph |
1638 | self.old_lines = None |
1639 | - |
1640 | + |
1641 | self.fileId = fileId |
1642 | self.path = path |
1643 | self.encoding = encoding |
1644 | @@ -294,7 +294,7 @@ |
1645 | self.loader_args = loader_args |
1646 | |
1647 | self.throbber = ToolBarThrobberWidget(self) |
1648 | - |
1649 | + |
1650 | self.text_edit_frame = AnnotateEditerFrameBase(self) |
1651 | self.text_edit = AnnotatedTextEdit(self) |
1652 | self.text_edit.setFrameStyle(QtGui.QFrame.NoFrame) |
1653 | @@ -302,7 +302,7 @@ |
1654 | QtCore.Qt.TextSelectableByMouse| |
1655 | QtCore.Qt.TextSelectableByKeyboard) |
1656 | self.text_edit.setLineWrapMode(QtGui.QPlainTextEdit.NoWrap) |
1657 | - |
1658 | + |
1659 | self.text_edit.document().setDefaultFont(get_monospace_font()) |
1660 | |
1661 | self.guidebar_panel = GuideBarPanel(self.text_edit, parent=self) |
1662 | @@ -313,26 +313,26 @@ |
1663 | annotate_spliter.addWidget(self.guidebar_panel) |
1664 | self.annotate_bar.splitter = annotate_spliter |
1665 | self.text_edit_frame.hbox.addWidget(annotate_spliter) |
1666 | - |
1667 | + |
1668 | self.connect(self.text_edit, |
1669 | QtCore.SIGNAL("cursorPositionChanged()"), |
1670 | - self.edit_cursorPositionChanged) |
1671 | + self.edit_cursorPositionChanged) |
1672 | self.connect(self.annotate_bar, |
1673 | QtCore.SIGNAL("cursorPositionChanged()"), |
1674 | self.edit_cursorPositionChanged) |
1675 | self.connect(self.text_edit, |
1676 | QtCore.SIGNAL("documentChangeFinished()"), |
1677 | self.edit_documentChangeFinished) |
1678 | - |
1679 | + |
1680 | self.log_list = AnnotateLogList(self.processEvents, self.throbber, self) |
1681 | self.log_list.header().hideSection(logmodel.COL_DATE) |
1682 | self.log_list.parent_annotate_window = self |
1683 | self.log_branch_loaded = False |
1684 | - |
1685 | + |
1686 | self.connect(self.log_list.selectionModel(), |
1687 | QtCore.SIGNAL("selectionChanged(QItemSelection, QItemSelection)"), |
1688 | self.log_list_selectionChanged) |
1689 | - |
1690 | + |
1691 | self.message = LogListRevisionMessageBrowser(self.log_list, self) |
1692 | |
1693 | self.encoding_selector = EncodingMenuSelector(self.encoding, |
1694 | @@ -361,15 +361,15 @@ |
1695 | self.show_find = QtGui.QAction(get_icon("edit-find"), gettext("Find"), self) |
1696 | self.show_find.setShortcuts(QtGui.QKeySequence.Find) |
1697 | self.show_find.setCheckable(True) |
1698 | - |
1699 | + |
1700 | self.show_goto_line = QtGui.QAction(get_icon("go-jump"), gettext("Goto Line"), self) |
1701 | self.show_goto_line.setShortcuts((QtCore.Qt.CTRL + QtCore.Qt.Key_L,)) |
1702 | self.show_goto_line.setCheckable(True) |
1703 | - |
1704 | + |
1705 | show_view_menu = QtGui.QAction(get_icon("document-properties"), gettext("&View Options"), self) |
1706 | view_menu = QtGui.QMenu(gettext('View Options'), self) |
1707 | show_view_menu.setMenu(view_menu) |
1708 | - |
1709 | + |
1710 | word_wrap = QtGui.QAction(gettext("Word Wrap"), self) |
1711 | word_wrap.setCheckable(True) |
1712 | self.connect(word_wrap, |
1713 | @@ -382,28 +382,28 @@ |
1714 | self.tab_width_selector = TabWidthMenuSelector(get_set_tab_width_chars(branch=branch), |
1715 | gettext("Tab Width"), |
1716 | setTabStopWidth) |
1717 | - |
1718 | + |
1719 | view_menu.addMenu(self.tab_width_selector) |
1720 | view_menu.addMenu(self.encoding_selector) |
1721 | view_menu.addAction(word_wrap) |
1722 | - |
1723 | + |
1724 | toolbar = self.addToolBar(gettext("Annotate")) |
1725 | toolbar.setMovable (False) |
1726 | toolbar.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon) |
1727 | - |
1728 | + |
1729 | #self.toolbar.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon) |
1730 | toolbar.addAction(self.show_find) |
1731 | toolbar.addAction(self.show_goto_line) |
1732 | toolbar.addAction(show_view_menu) |
1733 | toolbar.widgetForAction(show_view_menu).setPopupMode(QtGui.QToolButton.InstantPopup) |
1734 | - |
1735 | + |
1736 | spacer = QtGui.QWidget() |
1737 | spacer.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) |
1738 | - toolbar.addWidget(spacer) |
1739 | + toolbar.addWidget(spacer) |
1740 | toolbar.addWidget(self.throbber) |
1741 | - |
1742 | + |
1743 | self.addToolBarBreak() |
1744 | - |
1745 | + |
1746 | self.find_toolbar = FindToolbar(self, self.text_edit, self.show_find) |
1747 | self.find_toolbar.hide() |
1748 | self.addToolBar(self.find_toolbar) |
1749 | @@ -411,11 +411,11 @@ |
1750 | QtCore.SIGNAL("toggled (bool)"), |
1751 | self.show_find_toggle) |
1752 | setup_guidebar_for_find(self.guidebar_panel, self.find_toolbar, index=1) |
1753 | - |
1754 | + |
1755 | self.goto_line_toolbar = GotoLineToolbar(self, self.show_goto_line) |
1756 | self.goto_line_toolbar.hide() |
1757 | self.addToolBar(self.goto_line_toolbar) |
1758 | - |
1759 | + |
1760 | self.connect(self.show_goto_line, |
1761 | QtCore.SIGNAL("toggled (bool)"), |
1762 | self.show_goto_line_toggle ) |
1763 | @@ -479,7 +479,7 @@ |
1764 | self.set_title_and_icon([gettext("Annotate"), self.path, |
1765 | gettext("Revision %s") % revno]) |
1766 | return |
1767 | - |
1768 | + |
1769 | self.set_title_and_icon([gettext("Annotate"), self.path]) |
1770 | |
1771 | def get_revno(self, revid): |
1772 | @@ -488,7 +488,7 @@ |
1773 | revid in gv.revid_rev): |
1774 | return gv.revid_rev[revid].revno_str |
1775 | return "" |
1776 | - |
1777 | + |
1778 | def annotate(self, annotate_tree, fileId, path): |
1779 | self.now = time.time() |
1780 | self.rev_indexes = {} |
1781 | @@ -498,40 +498,40 @@ |
1782 | ordered_revids = [] |
1783 | |
1784 | self.processEvents() |
1785 | - for revid, text in annotate_tree.annotate_iter(path, file_id=fileId): |
1786 | + for revid, text in annotate_tree.annotate_iter(path): |
1787 | if revid == CURRENT_REVISION: |
1788 | - revid = CURRENT_REVISION + annotate_tree.basedir |
1789 | - |
1790 | + revid = CURRENT_REVISION + annotate_tree.basedir.encode("utf-8") |
1791 | + |
1792 | text = text.decode(self.encoding, 'replace') |
1793 | - |
1794 | + |
1795 | lines.append(text) |
1796 | - |
1797 | + |
1798 | text = text.rstrip() |
1799 | if revid not in self.rev_indexes: |
1800 | self.rev_indexes[revid]=[] |
1801 | ordered_revids.append(revid) |
1802 | self.rev_indexes[revid].append(len(annotate)) |
1803 | - |
1804 | + |
1805 | is_top = last_revid != revid |
1806 | last_revid = revid |
1807 | - |
1808 | + |
1809 | annotate.append((revid, is_top)) |
1810 | if len(annotate) % 100 == 0: |
1811 | self.processEvents() |
1812 | annotate.append((None, False)) # because the view has one more line |
1813 | - |
1814 | + |
1815 | new_positions = None |
1816 | if self.old_lines: |
1817 | # Try keep the scroll, and selection stable. |
1818 | old_positions, lines_to_center = self.text_edit.get_positions() |
1819 | new_positions = self.translate_positions( |
1820 | self.old_lines, lines, old_positions) |
1821 | - |
1822 | + |
1823 | self.text_edit.annotate = None |
1824 | self.text_edit.setPlainText("".join(lines)) |
1825 | if new_positions: |
1826 | self.text_edit.set_positions(new_positions, lines_to_center) |
1827 | - |
1828 | + |
1829 | self.old_lines = lines |
1830 | self.annotate_bar.adjustWidth(len(lines), 999) |
1831 | self.annotate_bar.annotate = annotate |
1832 | @@ -539,9 +539,9 @@ |
1833 | self.annotate_bar.show_current_line = False |
1834 | |
1835 | self.text_edit.emit(QtCore.SIGNAL("documentChangeFinished()")) |
1836 | - |
1837 | + |
1838 | self.processEvents() |
1839 | - |
1840 | + |
1841 | just_loaded_log = False |
1842 | if not self.log_branch_loaded: |
1843 | self.log_branch_loaded = True |
1844 | @@ -549,22 +549,22 @@ |
1845 | self.log_list.load( |
1846 | (bi,), bi, [self.fileId], self.no_graph, |
1847 | logmodel.WithWorkingTreeGraphVizLoader) |
1848 | - |
1849 | + |
1850 | gv = self.log_list.log_model.graph_viz |
1851 | self.annotate_bar.adjustWidth(len(lines), |
1852 | gv.revisions[0].revno_sequence[0]) |
1853 | - |
1854 | + |
1855 | just_loaded_log = True |
1856 | - |
1857 | + |
1858 | # Show the revisions the we know about from the annotate. |
1859 | filter = self.log_list.log_model.file_id_filter |
1860 | changed_revs = [] |
1861 | - for revid in self.rev_indexes.keys(): |
1862 | + for revid in list(self.rev_indexes.keys()): |
1863 | rev = gv.revid_rev[revid] |
1864 | filter.filter_file_id[rev.index] = True |
1865 | changed_revs.append(rev) |
1866 | filter.filter_changed_callback(changed_revs, last_call=True) |
1867 | - |
1868 | + |
1869 | self.processEvents() |
1870 | highlight_document(self.text_edit, path) |
1871 | self.processEvents() |
1872 | @@ -572,15 +572,15 @@ |
1873 | revisions_loaded = self.revisions_loaded, |
1874 | pass_prev_loaded_rev = True) |
1875 | self.processEvents() |
1876 | - |
1877 | + |
1878 | if just_loaded_log: |
1879 | # Check for any other revisions we don't know about |
1880 | - |
1881 | + |
1882 | filter = self.log_list.log_model.file_id_filter |
1883 | revids = [rev.revid for rev in gv.revisions |
1884 | if rev.revid not in self.rev_indexes] |
1885 | filter.load(revids) |
1886 | - |
1887 | + |
1888 | def translate_positions(self, old_lines, new_lines, old_positions): |
1889 | sm = SequenceMatcher(None, old_lines, new_lines) |
1890 | opcodes = sm.get_opcodes() |
1891 | @@ -614,13 +614,13 @@ |
1892 | return new_positions |
1893 | |
1894 | def revisions_loaded(self, revisions, last_call): |
1895 | - for rev in revisions.itervalues(): |
1896 | + for rev in revisions.values(): |
1897 | authors = rev.get_apparent_authors() |
1898 | - emails = map(self._maybe_extract_email, authors) |
1899 | + emails = list(map(self._maybe_extract_email, authors)) |
1900 | author_id = ';'.join(emails) |
1901 | |
1902 | if rev.timestamp is None: |
1903 | - days = sys.maxint |
1904 | + days = sys.maxsize |
1905 | elif self.now < rev.timestamp: |
1906 | days = 0 |
1907 | else: |
1908 | @@ -628,7 +628,7 @@ |
1909 | |
1910 | alpha = 0.5/((days/50) + 1) |
1911 | h_sh = self._get_hash(author_id) |
1912 | - hue = 1-float(h_sh) / sys.maxint |
1913 | + hue = 1-float(h_sh) / sys.maxsize |
1914 | color = QtGui.QColor.fromHsvF(hue, 1, 1, alpha) |
1915 | brush = QtGui.QBrush(color) |
1916 | |
1917 | @@ -679,7 +679,7 @@ |
1918 | try: |
1919 | self.branch.lock_read() |
1920 | try: |
1921 | - revid = str(self.log_list.currentIndex().data(logmodel.RevIdRole).toString()) |
1922 | + revid = self.log_list.currentIndex().data(logmodel.RevIdRole) |
1923 | if revid.startswith(CURRENT_REVISION): |
1924 | rev = cached_revisions[revid] |
1925 | self.annotate_tree = self.working_tree |
1926 | @@ -707,13 +707,13 @@ |
1927 | self.branch.unlock() |
1928 | finally: |
1929 | self.throbber.hide() |
1930 | - |
1931 | + |
1932 | def log_list_selectionChanged(self, selected, deselected): |
1933 | revids = self.log_list.get_selection_and_merged_revids() |
1934 | self.annotate_bar.highlight_revids = revids |
1935 | self.guidebar_panel.update_data(annotate=self.annotate_bar.highlight_lines) |
1936 | self.annotate_bar.update() |
1937 | - |
1938 | + |
1939 | def show_find_toggle(self, state): |
1940 | if state: |
1941 | self.show_goto_line.setChecked(False) |
1942 | @@ -725,7 +725,7 @@ |
1943 | self.show_find.setChecked(False) |
1944 | else: |
1945 | self.goto_line_toolbar.line_edit.setText('') |
1946 | - |
1947 | + |
1948 | def word_wrap_toggle(self, state): |
1949 | if state: |
1950 | self.text_edit.setLineWrapMode(QtGui.QPlainTextEdit.WidgetWidth) |
1951 | @@ -741,14 +741,17 @@ |
1952 | |
1953 | |
1954 | # QIntValidator did not work on vila's setup, so this is a workaround. |
1955 | +# RJLRJL QIntValidator seems to be working in 2020, whereas this isn't |
1956 | +# so ignored for now. |
1957 | class IntValidator(QtGui.QValidator): |
1958 | def validate (self, input, pos): |
1959 | if input == '': |
1960 | return (QtGui.QValidator.Intermediate, pos) |
1961 | - try: |
1962 | + try: |
1963 | i = int(input) |
1964 | except ValueError: |
1965 | return (QtGui.QValidator.Invalid, pos) |
1966 | + |
1967 | if i > 0: |
1968 | return (QtGui.QValidator.Acceptable, pos) |
1969 | else: |
1970 | @@ -756,50 +759,46 @@ |
1971 | |
1972 | |
1973 | class GotoLineToolbar(QtGui.QToolBar): |
1974 | - |
1975 | + |
1976 | def __init__(self, anotate_window, show_action): |
1977 | QtGui.QToolBar.__init__(self, gettext("Goto Line"), anotate_window) |
1978 | self.anotate_window = anotate_window |
1979 | if 0: self.anotate_window = AnnotateWindow() |
1980 | self.show_action = show_action |
1981 | - |
1982 | + |
1983 | self.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon) |
1984 | self.setMovable (False) |
1985 | - |
1986 | + |
1987 | label = QtGui.QLabel(gettext("Goto Line: "), self) |
1988 | self.addWidget(label) |
1989 | - |
1990 | + |
1991 | self.line_edit = QtGui.QLineEdit(self) |
1992 | - self.line_edit.setValidator(IntValidator(self.line_edit)) |
1993 | + # QIntValidator is working in python3, so we'll use that |
1994 | + # self.line_edit.setValidator(IntValidator(self.line_edit)) |
1995 | + self.line_edit.setValidator(QtGui.QIntValidator()) |
1996 | self.addWidget(self.line_edit) |
1997 | label.setBuddy(self.line_edit) |
1998 | - |
1999 | + |
2000 | go = self.addAction(get_icon("go-next"), gettext("Go")) |
2001 | - |
2002 | + |
2003 | spacer = QtGui.QWidget() |
2004 | - spacer.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) |
2005 | + spacer.setSizePolicy(QtGui.QSizePolicy.Expanding, |
2006 | + QtGui.QSizePolicy.Expanding) |
2007 | self.addWidget(spacer) |
2008 | - |
2009 | + |
2010 | close = QtGui.QAction(self) |
2011 | - close.setIcon(self.style().standardIcon( |
2012 | - QtGui.QStyle.SP_DialogCloseButton)) |
2013 | + close.setIcon(self.style().standardIcon(QtGui.QStyle.SP_DialogCloseButton)) |
2014 | self.addAction(close) |
2015 | close.setShortcut((QtCore.Qt.Key_Escape)) |
2016 | close.setShortcutContext(QtCore.Qt.WidgetWithChildrenShortcut) |
2017 | close.setStatusTip(gettext("Close Goto Line")) |
2018 | - self.connect(close, |
2019 | - QtCore.SIGNAL("triggered(bool)"), |
2020 | - self.close_triggered) |
2021 | - self.connect(go, |
2022 | - QtCore.SIGNAL("triggered(bool)"), |
2023 | - self.go_triggered) |
2024 | - self.connect(self.line_edit, |
2025 | - QtCore.SIGNAL("returnPressed()"), |
2026 | - self.go_triggered) |
2027 | - |
2028 | + self.connect(close, QtCore.SIGNAL("triggered(bool)"), self.close_triggered) |
2029 | + self.connect(go, QtCore.SIGNAL("triggered(bool)"), self.go_triggered) |
2030 | + self.connect(self.line_edit, QtCore.SIGNAL("returnPressed()"), self.go_triggered) |
2031 | + |
2032 | def close_triggered(self, state): |
2033 | self.show_action.setChecked(False) |
2034 | - |
2035 | + |
2036 | def go_triggered(self, state=True): |
2037 | try: |
2038 | line = int(str(self.line_edit.text())) |
2039 | @@ -811,19 +810,15 @@ |
2040 | |
2041 | |
2042 | class AnnotateLogList(LogList): |
2043 | - |
2044 | + |
2045 | parent_annotate_window = None |
2046 | - |
2047 | + |
2048 | def create_context_menu(self): |
2049 | LogList.create_context_menu(self, diff_is_default_action=False) |
2050 | - set_rev_action = QtGui.QAction(gettext("&Annotate this revision"), |
2051 | - self.context_menu) |
2052 | - self.connect(set_rev_action, QtCore.SIGNAL('triggered()'), |
2053 | - self.parent_annotate_window.set_annotate_revision) |
2054 | - self.context_menu.insertAction( |
2055 | - self.context_menu.actions()[0], |
2056 | - set_rev_action) |
2057 | + set_rev_action = QtGui.QAction(gettext("&Annotate this revision"), self.context_menu) |
2058 | + self.connect(set_rev_action, QtCore.SIGNAL('triggered()'), self.parent_annotate_window.set_annotate_revision) |
2059 | + self.context_menu.insertAction(self.context_menu.actions()[0], set_rev_action) |
2060 | self.context_menu.setDefaultAction(set_rev_action) |
2061 | - |
2062 | + |
2063 | def default_action(self, index=None): |
2064 | self.parent_annotate_window.set_annotate_revision() |
2065 | |
2066 | === modified file 'lib/autocomplete.py' |
2067 | --- lib/autocomplete.py 2008-11-04 15:15:48 +0000 |
2068 | +++ lib/autocomplete.py 2020-07-16 14:28:25 +0000 |
2069 | @@ -68,7 +68,7 @@ |
2070 | |
2071 | def compile_regexes(self): |
2072 | if self.compiled_regexes is None: |
2073 | - self.compiled_regexes = map(re.compile, self.regexes) |
2074 | + self.compiled_regexes = list(map(re.compile, self.regexes)) |
2075 | |
2076 | def iter_words(self, file): |
2077 | self.compile_regexes() |
2078 | @@ -77,7 +77,7 @@ |
2079 | for result in regex.findall(line): |
2080 | if not isinstance(result, tuple): |
2081 | result = (result,) |
2082 | - for word in filter(None, result): |
2083 | + for word in [_f for _f in result if _f]: |
2084 | yield word |
2085 | |
2086 | |
2087 | |
2088 | === modified file 'lib/bind.py' |
2089 | --- lib/bind.py 2017-09-11 06:53:22 +0000 |
2090 | +++ lib/bind.py 2020-07-16 14:28:25 +0000 |
2091 | @@ -113,7 +113,7 @@ |
2092 | self.branch_combo.setCurrentIndex(0) |
2093 | |
2094 | def _get_location(self): |
2095 | - return unicode(self.branch_combo.currentText()) |
2096 | + return str(self.branch_combo.currentText()) |
2097 | |
2098 | def validate(self): |
2099 | if not self._get_location(): |
2100 | |
2101 | === modified file 'lib/branch.py' |
2102 | --- lib/branch.py 2017-09-11 06:53:22 +0000 |
2103 | +++ lib/branch.py 2020-07-16 14:28:25 +0000 |
2104 | @@ -49,7 +49,7 @@ |
2105 | # Unless instructed otherwise, use the current directory as |
2106 | # the parent directory. |
2107 | if parent_dir is None: |
2108 | - parent_dir = os.getcwdu() |
2109 | + parent_dir = os.getcwd() |
2110 | self.parent_dir = parent_dir |
2111 | |
2112 | # Layout the form, adding the subprocess widgets |
2113 | @@ -68,7 +68,7 @@ |
2114 | |
2115 | # Initialise the fields |
2116 | fill_combo_with(self.ui.from_location, |
2117 | - u'', |
2118 | + '', |
2119 | iter_saved_pull_locations()) |
2120 | if from_location: |
2121 | self.ui.from_location.setEditText(from_location) |
2122 | @@ -96,7 +96,7 @@ |
2123 | self.ui.from_location.setFocus() |
2124 | |
2125 | def from_changed(self, from_location): |
2126 | - to_location = self._default_to_location(unicode(from_location)) |
2127 | + to_location = self._default_to_location(str(from_location)) |
2128 | if to_location is not None: |
2129 | self.ui.to_location.setEditText(to_location) |
2130 | |
2131 | @@ -129,7 +129,7 @@ |
2132 | def get_to_location(self): |
2133 | """The path the branch was created in.""" |
2134 | # This is used by explorer to find the location to open on completion |
2135 | - return unicode(self.ui.to_location.currentText()) |
2136 | + return str(self.ui.to_location.currentText()) |
2137 | |
2138 | def do_start(self): |
2139 | args = [] |
2140 | @@ -139,7 +139,7 @@ |
2141 | if revision: |
2142 | args.append('--revision') |
2143 | args.append(revision) |
2144 | - from_location = unicode(self.ui.from_location.currentText()) |
2145 | + from_location = str(self.ui.from_location.currentText()) |
2146 | to_location = self.get_to_location() |
2147 | if 'use-existing-dir' in self.cmd_branch_options: |
2148 | # always use this options because it should be mostly harmless |
2149 | |
2150 | === modified file 'lib/browse.py' |
2151 | --- lib/browse.py 2017-09-11 06:53:22 +0000 |
2152 | +++ lib/browse.py 2020-07-16 14:28:25 +0000 |
2153 | @@ -214,7 +214,7 @@ |
2154 | |
2155 | @ui_current_widget |
2156 | def reload_tree(self): |
2157 | - revstr = unicode(self.revision_edit.text()) |
2158 | + revstr = str(self.revision_edit.text()) |
2159 | if not revstr: |
2160 | if self.workingtree is not None: |
2161 | self.revision_spec = "wt:" |
2162 | @@ -231,7 +231,7 @@ |
2163 | else: |
2164 | try: |
2165 | revspec = RevisionSpec.from_string(revstr) |
2166 | - except errors.NoSuchRevisionSpec, e: |
2167 | + except errors.NoSuchRevisionSpec as e: |
2168 | QtGui.QMessageBox.warning(self, |
2169 | gettext("Browse"), str(e), |
2170 | QtGui.QMessageBox.Ok) |
2171 | |
2172 | === modified file 'lib/bugs.py' |
2173 | --- lib/bugs.py 2017-09-11 06:53:22 +0000 |
2174 | +++ lib/bugs.py 2020-07-16 14:28:25 +0000 |
2175 | @@ -91,7 +91,7 @@ |
2176 | else: |
2177 | branch = FakeBranchForBugs() |
2178 | # try to convert bug urls to tag:id values |
2179 | - for k,n in urls_dict.iteritems(): |
2180 | + for k,n in urls_dict.items(): |
2181 | for tag in bug_tags: |
2182 | url = bugtracker.get_bug_url(tag, branch, n) |
2183 | if url == k: |
2184 | @@ -124,7 +124,7 @@ |
2185 | def get_global_bug_tags(): |
2186 | """Return bug tags collected from global config bazaar.conf""" |
2187 | cfg = config.GlobalConfig() |
2188 | - keys = cfg._get_parser().get('DEFAULT', {}).keys() |
2189 | + keys = list(cfg._get_parser().get('DEFAULT', {}).keys()) |
2190 | return get_user_bug_trackers_tags(keys) |
2191 | |
2192 | def get_branch_bug_tags(branch): |
2193 | |
2194 | === modified file 'lib/cat.py' |
2195 | --- lib/cat.py 2017-11-13 23:31:28 +0000 |
2196 | +++ lib/cat.py 2020-07-16 14:28:25 +0000 |
2197 | @@ -69,7 +69,7 @@ |
2198 | tree=None, file_id=None, encoding=None, |
2199 | parent=None): |
2200 | """Create qcat window.""" |
2201 | - |
2202 | + |
2203 | self.filename = filename |
2204 | self.revision = revision |
2205 | self.tree = tree |
2206 | @@ -112,7 +112,7 @@ |
2207 | # we show the bare form as soon as possible. |
2208 | QBzrWindow.show(self) |
2209 | QtCore.QTimer.singleShot(0, self.load) |
2210 | - |
2211 | + |
2212 | @runs_in_loading_queue |
2213 | @ui_current_widget |
2214 | @reports_exception() |
2215 | @@ -131,24 +131,24 @@ |
2216 | else: |
2217 | revision_id = self.revision[0].in_branch(branch).rev_id |
2218 | self.tree = branch.repository.revision_tree(revision_id) |
2219 | - |
2220 | + |
2221 | self.file_id = self.tree.path2id(relpath) |
2222 | - |
2223 | + |
2224 | if not self.file_id: |
2225 | self.file_id = self.tree.path2id(self.filename) |
2226 | - |
2227 | + |
2228 | if not self.file_id: |
2229 | raise errors.BzrCommandError( |
2230 | "%r is not present in revision %s" % ( |
2231 | self.filename, self.tree.get_revision_id())) |
2232 | - |
2233 | + |
2234 | self.tree.lock_read() |
2235 | try: |
2236 | - kind = self.tree.kind(self.filename, self.file_id) |
2237 | + kind = self.tree.kind(self.filename) |
2238 | if kind == 'file': |
2239 | - text = self.tree.get_file_text(self.filename, self.file_id) |
2240 | + text = self.tree.get_file_text(self.filename) |
2241 | elif kind == 'symlink': |
2242 | - text = self.tree.get_symlink_target(self.filename, self.file_id) |
2243 | + text = self.tree.get_symlink_target(self.filename) |
2244 | else: |
2245 | text = '' |
2246 | finally: |
2247 | @@ -184,7 +184,7 @@ |
2248 | Supported file types: text, image, binary |
2249 | """ |
2250 | if kind == 'file': |
2251 | - if not '\0' in text: |
2252 | + if not b'\0' in text: |
2253 | return 'text file', self._create_text_view |
2254 | else: |
2255 | ext = file_extension(relpath).lower() |
2256 | @@ -331,6 +331,7 @@ |
2257 | # make temp file |
2258 | import os |
2259 | import tempfile |
2260 | + # RJLRJL Check this QBzr reference |
2261 | qdir = os.path.join(tempfile.gettempdir(), 'QBzr', 'qcat') |
2262 | if not os.path.isdir(qdir): |
2263 | os.makedirs(qdir) |
2264 | |
2265 | === added file 'lib/cleanup.py' |
2266 | --- lib/cleanup.py 1970-01-01 00:00:00 +0000 |
2267 | +++ lib/cleanup.py 2020-07-16 14:28:25 +0000 |
2268 | @@ -0,0 +1,184 @@ |
2269 | +# Copyright (C) 2009, 2010 Canonical Ltd |
2270 | +# |
2271 | +# This program is free software; you can redistribute it and/or modify |
2272 | +# it under the terms of the GNU General Public License as published by |
2273 | +# the Free Software Foundation; either version 2 of the License, or |
2274 | +# (at your option) any later version. |
2275 | +# |
2276 | +# This program is distributed in the hope that it will be useful, |
2277 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
2278 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2279 | +# GNU General Public License for more details. |
2280 | +# |
2281 | +# You should have received a copy of the GNU General Public License |
2282 | +# along with this program; if not, write to the Free Software |
2283 | +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
2284 | + |
2285 | +"""Helpers for managing cleanup functions and the errors they might raise. |
2286 | + |
2287 | +The usual way to run cleanup code in Python is:: |
2288 | + |
2289 | + try: |
2290 | + do_something() |
2291 | + finally: |
2292 | + cleanup_something() |
2293 | + |
2294 | +However if both `do_something` and `cleanup_something` raise an exception |
2295 | +Python will forget the original exception and propagate the one from |
2296 | +cleanup_something. Unfortunately, this is almost always much less useful than |
2297 | +the original exception. |
2298 | + |
2299 | +If you want to be certain that the first, and only the first, error is raised, |
2300 | +then use:: |
2301 | + |
2302 | + operation = OperationWithCleanups(do_something) |
2303 | + operation.add_cleanup(cleanup_something) |
2304 | + operation.run_simple() |
2305 | + |
2306 | +This is more inconvenient (because you need to make every try block a |
2307 | +function), but will ensure that the first error encountered is the one raised, |
2308 | +while also ensuring all cleanups are run. See OperationWithCleanups for more |
2309 | +details. |
2310 | +""" |
2311 | + |
2312 | +from __future__ import absolute_import |
2313 | + |
2314 | +from collections import deque |
2315 | +# import sys |
2316 | +# from . import ( |
2317 | +# debug, |
2318 | +# trace, |
2319 | +# ) |
2320 | + |
2321 | +from breezy import ( |
2322 | + debug, |
2323 | + trace, |
2324 | + ) |
2325 | + |
2326 | + |
2327 | +def _log_cleanup_error(exc): |
2328 | + trace.mutter('Cleanup failed:') |
2329 | + trace.log_exception_quietly() |
2330 | + if 'cleanup' in debug.debug_flags: |
2331 | + trace.warning('brz: warning: Cleanup failed: %s', exc) |
2332 | + |
2333 | + |
2334 | +def _run_cleanup(func, *args, **kwargs): |
2335 | + """Run func(*args, **kwargs), logging but not propagating any error it |
2336 | + raises. |
2337 | + |
2338 | + :returns: True if func raised no errors, else False. |
2339 | + """ |
2340 | + try: |
2341 | + func(*args, **kwargs) |
2342 | + except KeyboardInterrupt: |
2343 | + raise |
2344 | + except Exception as exc: |
2345 | + _log_cleanup_error(exc) |
2346 | + return False |
2347 | + return True |
2348 | + |
2349 | + |
2350 | +def _run_cleanups(funcs): |
2351 | + """Run a series of cleanup functions.""" |
2352 | + for func, args, kwargs in funcs: |
2353 | + _run_cleanup(func, *args, **kwargs) |
2354 | + |
2355 | + |
2356 | +class ObjectWithCleanups(object): |
2357 | + """A mixin for objects that hold a cleanup list. |
2358 | + |
2359 | + Subclass or client code can call add_cleanup and then later `cleanup_now`. |
2360 | + """ |
2361 | + def __init__(self): |
2362 | + self.cleanups = deque() |
2363 | + |
2364 | + def add_cleanup(self, cleanup_func, *args, **kwargs): |
2365 | + """Add a cleanup to run. |
2366 | + |
2367 | + Cleanups may be added at any time. |
2368 | + Cleanups will be executed in LIFO order. |
2369 | + """ |
2370 | + self.cleanups.appendleft((cleanup_func, args, kwargs)) |
2371 | + |
2372 | + def cleanup_now(self): |
2373 | + _run_cleanups(self.cleanups) |
2374 | + self.cleanups.clear() |
2375 | + |
2376 | + |
2377 | +class OperationWithCleanups(ObjectWithCleanups): |
2378 | + """A way to run some code with a dynamic cleanup list. |
2379 | + |
2380 | + This provides a way to add cleanups while the function-with-cleanups is |
2381 | + running. |
2382 | + |
2383 | + Typical use:: |
2384 | + |
2385 | + operation = OperationWithCleanups(some_func) |
2386 | + operation.run(args...) |
2387 | + |
2388 | + where `some_func` is:: |
2389 | + |
2390 | + def some_func(operation, args, ...): |
2391 | + do_something() |
2392 | + operation.add_cleanup(something) |
2393 | + # etc |
2394 | + |
2395 | + Note that the first argument passed to `some_func` will be the |
2396 | + OperationWithCleanups object. To invoke `some_func` without that, use |
2397 | + `run_simple` instead of `run`. |
2398 | + """ |
2399 | + |
2400 | + def __init__(self, func): |
2401 | + super(OperationWithCleanups, self).__init__() |
2402 | + self.func = func |
2403 | + |
2404 | + def run(self, *args, **kwargs): |
2405 | + return _do_with_cleanups(self.cleanups, self.func, self, *args, **kwargs) |
2406 | + |
2407 | + def run_simple(self, *args, **kwargs): |
2408 | + return _do_with_cleanups(self.cleanups, self.func, *args, **kwargs) |
2409 | + |
2410 | + |
2411 | +def _do_with_cleanups(cleanup_funcs, func, *args, **kwargs): |
2412 | + """Run `func`, then call all the cleanup_funcs. |
2413 | + |
2414 | + All the cleanup_funcs are guaranteed to be run. The first exception raised |
2415 | + by func or any of the cleanup_funcs is the one that will be propagted by |
2416 | + this function (subsequent errors are caught and logged). |
2417 | + |
2418 | + Conceptually similar to:: |
2419 | + |
2420 | + try: |
2421 | + return func(*args, **kwargs) |
2422 | + finally: |
2423 | + for cleanup, cargs, ckwargs in cleanup_funcs: |
2424 | + cleanup(*cargs, **ckwargs) |
2425 | + |
2426 | + It avoids several problems with using try/finally directly: |
2427 | + * an exception from func will not be obscured by a subsequent exception |
2428 | + from a cleanup. |
2429 | + * an exception from a cleanup will not prevent other cleanups from |
2430 | + running (but the first exception encountered is still the one |
2431 | + propagated). |
2432 | + |
2433 | + Unike `_run_cleanup`, `_do_with_cleanups` can propagate an exception from a |
2434 | + cleanup, but only if there is no exception from func. |
2435 | + """ |
2436 | + try: |
2437 | + result = func(*args, **kwargs) |
2438 | + except: |
2439 | + # We have an exception from func already, so suppress cleanup errors. |
2440 | + _run_cleanups(cleanup_funcs) |
2441 | + raise |
2442 | + # No exception from func, so allow first cleanup error to propgate. |
2443 | + pending_cleanups = iter(cleanup_funcs) |
2444 | + try: |
2445 | + for cleanup, c_args, c_kwargs in pending_cleanups: |
2446 | + cleanup(*c_args, **c_kwargs) |
2447 | + except: |
2448 | + # Still run the remaining cleanups but suppress any further errors. |
2449 | + _run_cleanups(pending_cleanups) |
2450 | + raise |
2451 | + # No error, so we can return the result |
2452 | + return result |
2453 | |
2454 | === modified file 'lib/commands.py' |
2455 | --- lib/commands.py 2017-09-11 06:53:22 +0000 |
2456 | +++ lib/commands.py 2020-07-16 14:28:25 +0000 |
2457 | @@ -19,6 +19,7 @@ |
2458 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
2459 | |
2460 | import signal |
2461 | +import contextlib |
2462 | |
2463 | from breezy import errors |
2464 | from breezy.commands import Command |
2465 | @@ -40,6 +41,7 @@ |
2466 | from breezy.branch import Branch |
2467 | from breezy.controldir import ControlDir |
2468 | from breezy.workingtree import WorkingTree |
2469 | +from breezy.diff import get_trees_and_branches_to_diff_locked |
2470 | |
2471 | from breezy.plugins.qbrz.lib import i18n |
2472 | from breezy.plugins.qbrz.lib.add import AddWindow |
2473 | @@ -85,7 +87,7 @@ |
2474 | |
2475 | from breezy.plugins.qbrz.lib.diff_arg import DiffArgProvider |
2476 | |
2477 | -CUR_DIR=u'.' |
2478 | +CUR_DIR='.' |
2479 | |
2480 | class InvalidEncodingOption(errors.BzrError): |
2481 | |
2482 | @@ -96,8 +98,7 @@ |
2483 | errors.BzrError.__init__(self) |
2484 | self.encoding = encoding |
2485 | import encodings |
2486 | - self.valid = ', '.join(sorted(list( |
2487 | - set(encodings.aliases.aliases.values())))).replace('_','-') |
2488 | + self.valid = ', '.join(sorted(list(set(encodings.aliases.aliases.values())))).replace('_','-') |
2489 | |
2490 | |
2491 | def check_encoding(encoding): |
2492 | @@ -108,8 +109,7 @@ |
2493 | |
2494 | class PyQt4NotInstalled(errors.BzrError): |
2495 | |
2496 | - _fmt = ('QBzr require at least PyQt 4.4 and ' |
2497 | - 'Qt 4.4 to run. Please check your install') |
2498 | + _fmt = ('QBrz requires at least PyQt 4.4 and Qt 4.4 to run. Please check your install') |
2499 | |
2500 | |
2501 | def report_missing_pyqt(unbound): |
2502 | @@ -120,7 +120,7 @@ |
2503 | def run(self, *args, **kwargs): |
2504 | try: |
2505 | return unbound(self, *args, **kwargs) |
2506 | - except ImportError, e: |
2507 | + except ImportError as e: |
2508 | if str(e).endswith('PyQt4'): |
2509 | raise PyQt4NotInstalled |
2510 | raise |
2511 | @@ -163,10 +163,10 @@ |
2512 | std_ui_factory = ui.ui_factory |
2513 | try: |
2514 | ui.ui_factory = QUIFactory() |
2515 | - |
2516 | + |
2517 | # Handle interupt signal correctly. |
2518 | signal.signal(signal.SIGINT, signal.SIG_DFL) |
2519 | - |
2520 | + |
2521 | # Set up global exception handling. |
2522 | from breezy.plugins.qbrz.lib.trace import excepthook |
2523 | sys.excepthook = excepthook |
2524 | @@ -195,11 +195,9 @@ |
2525 | ui.ui_factory = std_ui_factory |
2526 | |
2527 | |
2528 | -ui_mode_option = Option("ui-mode", |
2529 | - help="Causes dialogs to wait after the operation is complete.") |
2530 | +ui_mode_option = Option("ui-mode", help="Causes dialogs to wait after the operation is complete.") |
2531 | execute_option = Option("execute", short_name='e', |
2532 | - help="Causes dialogs to start the underlying action immediately without " |
2533 | - "waiting for user input.") |
2534 | + help="Causes dialogs to start the underlying action immediately without waiting for user input.") |
2535 | |
2536 | # A special option so 'revision' can be passed as a simple string, when we do |
2537 | # *not* want breezy's feature of parsing the revision string before passing it. |
2538 | @@ -209,23 +207,23 @@ |
2539 | # 'revision' as normal. |
2540 | simple_revision_option = Option("revision", |
2541 | short_name='r', |
2542 | - type=unicode, |
2543 | + type=str, |
2544 | help='See "help revisionspec" for details.') |
2545 | |
2546 | |
2547 | -def bzr_option(cmd_name, opt_name): |
2548 | - """Helper so we can 'borrow' options from bzr itself without needing to |
2549 | +def brz_option(cmd_name, opt_name): |
2550 | + """Helper so we can 'borrow' options from brz itself without needing to |
2551 | duplicate the help text etc. Pass the builtin bzr command name and an |
2552 | option name. |
2553 | |
2554 | eg: |
2555 | - takes_options = [bzr_option("push", "create-prefix")] |
2556 | + takes_options = [brz_option("push", "create-prefix")] |
2557 | |
2558 | would give a command the exact same '--create-prefix' option as bzr's |
2559 | push command has, including help text, parsing, etc. |
2560 | """ |
2561 | from breezy.commands import get_cmd_object |
2562 | - cmd=get_cmd_object(cmd_name, False) |
2563 | + cmd = get_cmd_object(cmd_name, False) |
2564 | return cmd.options()[opt_name] |
2565 | |
2566 | |
2567 | @@ -233,13 +231,10 @@ |
2568 | """Show the origin of each line in a file.""" |
2569 | takes_args = ['filename'] |
2570 | takes_options = ['revision', |
2571 | - Option('encoding', type=check_encoding, |
2572 | - help='Encoding of files content (default: utf-8).'), |
2573 | + Option('encoding', type=check_encoding, help='Encoding of files content (default: utf-8).'), |
2574 | ui_mode_option, |
2575 | Option('no-graph', help="Shows the log with no graph."), |
2576 | - Option('line', short_name='L', type=int, argname='N', |
2577 | - param_name='activate_line', |
2578 | - help='Activate line N on start.'), |
2579 | + Option('line', short_name='L', type=int, argname='N', param_name='activate_line', help='Activate line N on start.'), |
2580 | ] |
2581 | aliases = ['qann', 'qblame'] |
2582 | |
2583 | @@ -248,8 +243,7 @@ |
2584 | back to this function to process the command-line args and convert |
2585 | them into the branch and tree etc needed by the UI. |
2586 | """ |
2587 | - wt, branch, relpath = \ |
2588 | - ControlDir.open_containing_tree_or_branch(filename) |
2589 | + wt, branch, relpath = ControlDir.open_containing_tree_or_branch(filename) |
2590 | if wt is not None: |
2591 | wt.lock_read() |
2592 | else: |
2593 | @@ -259,23 +253,18 @@ |
2594 | if wt is not None: |
2595 | tree = wt |
2596 | else: |
2597 | - tree = branch.repository.revision_tree( |
2598 | - branch.last_revision()) |
2599 | + tree = branch.repository.revision_tree(branch.last_revision()) |
2600 | elif len(revision) != 1: |
2601 | - raise errors.BzrCommandError( |
2602 | - 'bzr qannotate --revision takes exactly 1 argument') |
2603 | + raise errors.BzrCommandError('brz qannotate --revision takes exactly 1 argument') |
2604 | else: |
2605 | - tree = branch.repository.revision_tree( |
2606 | - revision_id = revision[0].in_history(branch).rev_id) |
2607 | + tree = branch.repository.revision_tree(revision_id = revision[0].in_history(branch).rev_id) |
2608 | |
2609 | file_id = tree.path2id(relpath) |
2610 | if file_id is None: |
2611 | raise errors.NotVersionedError(filename) |
2612 | - [(path, entry)] = list(tree.iter_entries_by_dir( |
2613 | - specific_file_ids=[file_id])) |
2614 | + [(path, entry)] = list(tree.iter_entries_by_dir(specific_files=[filename])) |
2615 | if entry.kind != 'file': |
2616 | - raise errors.BzrCommandError( |
2617 | - 'bzr qannotate only works for files (got %r)' % entry.kind) |
2618 | + raise errors.BzrCommandError('brz qannotate only works for files (got %r)' % entry.kind) |
2619 | #repo = branch.repository |
2620 | #w = repo.weave_store.get_weave(file_id, repo.get_transaction()) |
2621 | #content = list(w.annotate_iter(entry.revision)) |
2622 | @@ -307,7 +296,10 @@ |
2623 | takes_options = [ui_mode_option] |
2624 | |
2625 | def _qbrz_run(self, selected_list=None, ui_mode=False): |
2626 | + # print('\n:: cmd_add was passed ', selected_list) |
2627 | tree, selected_list = WorkingTree.open_containing_paths(selected_list) |
2628 | + # print('\n::: cmd_add started', tree, selected_list) |
2629 | + |
2630 | if selected_list == ['']: |
2631 | selected_list = None |
2632 | self.main_window = AddWindow(tree, selected_list, dialog=False, ui_mode=ui_mode) |
2633 | @@ -318,7 +310,7 @@ |
2634 | class cmd_qrevert(QBzrCommand): |
2635 | """Revert changes files.""" |
2636 | takes_args = ['selected*'] |
2637 | - takes_options = [ui_mode_option, bzr_option('revert', 'no-backup')] |
2638 | + takes_options = [ui_mode_option, brz_option('revert', 'no-backup')] |
2639 | |
2640 | def _qbrz_run(self, selected_list=None, ui_mode=False, no_backup=False): |
2641 | tree, selected_list = WorkingTree.open_containing_paths(selected_list) |
2642 | @@ -351,7 +343,7 @@ |
2643 | aliases = ['qbw'] |
2644 | |
2645 | def _qbrz_run(self, revision=None, location=None): |
2646 | - Branch.open_containing(location or u'.') # if there is no branch we want NotBranchError raised |
2647 | + Branch.open_containing(location or '.') # if there is no branch we want NotBranchError raised |
2648 | if revision is None: |
2649 | win = BrowseWindow(location = location) |
2650 | else: |
2651 | @@ -364,9 +356,9 @@ |
2652 | """GUI for committing revisions.""" |
2653 | takes_args = ['selected*'] |
2654 | takes_options = [ |
2655 | - bzr_option('commit', 'message'), |
2656 | - bzr_option('commit', 'local'), |
2657 | - bzr_option('commit', 'file'), |
2658 | + brz_option('commit', 'message'), |
2659 | + brz_option('commit', 'local'), |
2660 | + brz_option('commit', 'file'), |
2661 | Option('file-encoding', type=check_encoding, |
2662 | help='Encoding of commit message file content.'), |
2663 | ui_mode_option, |
2664 | @@ -407,31 +399,25 @@ |
2665 | Option('renamed', short_name='R', help='Show diff for renamed files.'), |
2666 | Option('ignore-whitespace', short_name='w', |
2667 | help="Ignore whitespace when finding differences"), |
2668 | - bzr_option('diff', 'old'), |
2669 | - bzr_option('diff', 'new'), |
2670 | + brz_option('diff', 'old'), |
2671 | + brz_option('diff', 'new'), |
2672 | ] |
2673 | if 'change' in Option.OPTIONS: |
2674 | takes_options.append('change') |
2675 | aliases = ['qdi'] |
2676 | |
2677 | def get_diff_window_args(self, processEvents, add_cleanup): |
2678 | + # RJL if you get a ``AttributeError: 'function' object has no attribute 'enter_context'`` |
2679 | + # error, or something similar, use something like: |
2680 | + # |
2681 | + # exit_stack = contextlib.ExitStack() |
2682 | + # |
2683 | + # and pass that as add_cleanup |
2684 | + # |
2685 | args = {} |
2686 | - try: |
2687 | - from breezy.diff import get_trees_and_branches_to_diff_locked |
2688 | - except ImportError: |
2689 | - from breezy.diff import get_trees_and_branches_to_diff |
2690 | - (args["old_tree"], args["new_tree"], |
2691 | - args["old_branch"], args["new_branch"], |
2692 | - args["specific_files"], _) = \ |
2693 | - get_trees_and_branches_to_diff( |
2694 | - self.file_list, self.revision, self.old, self.new) |
2695 | - else: |
2696 | - (args["old_tree"], args["new_tree"], |
2697 | - args["old_branch"], args["new_branch"], |
2698 | - args["specific_files"], _) = \ |
2699 | - get_trees_and_branches_to_diff_locked( |
2700 | - self.file_list, self.revision, self.old, self.new, |
2701 | - add_cleanup) |
2702 | + (args["old_tree"], args["new_tree"], |
2703 | + args["old_branch"], args["new_branch"], |
2704 | + args["specific_files"], _) = get_trees_and_branches_to_diff_locked(self.file_list, self.revision, self.old, self.new, add_cleanup) |
2705 | args["ignore_whitespace"] = self.ignore_whitespace |
2706 | return args |
2707 | |
2708 | @@ -459,8 +445,7 @@ |
2709 | old=None, new=None, ui_mode=False): |
2710 | |
2711 | if revision and len(revision) > 2: |
2712 | - raise errors.BzrCommandError('bzr qdiff --revision takes exactly' |
2713 | - ' one or two revision specifiers') |
2714 | + raise errors.BzrCommandError('brz qdiff --revision takes exactly one or two revision specifiers') |
2715 | # changes filter |
2716 | filter_options = FilterOptions(added=added, deleted=deleted, |
2717 | modified=modified, renamed=renamed) |
2718 | @@ -474,11 +459,7 @@ |
2719 | self.new = new |
2720 | self.ignore_whitespace = ignore_whitespace |
2721 | |
2722 | - window = DiffWindow(self, |
2723 | - complete=complete, |
2724 | - encoding=encoding, |
2725 | - filter_options=filter_options, |
2726 | - ui_mode=ui_mode) |
2727 | + window = DiffWindow(self, complete=complete, encoding=encoding, filter_options=filter_options, ui_mode=ui_mode) |
2728 | window.show() |
2729 | self._application.exec_() |
2730 | |
2731 | @@ -508,14 +489,11 @@ |
2732 | takes_options = [ |
2733 | ui_mode_option, |
2734 | Option('no-graph', help="Shows the log with no graph."), |
2735 | - Option('show-trees', help="Show working trees that have changes " |
2736 | - "as nodes in the graph"), |
2737 | + Option('show-trees', help="Show working trees that have changes as nodes in the graph"), |
2738 | ] |
2739 | |
2740 | - def _qbrz_run(self, locations_list=None, ui_mode=False, no_graph=False, |
2741 | - show_trees=False): |
2742 | - window = LogWindow(locations_list, None, None, ui_mode=ui_mode, |
2743 | - no_graph=no_graph, show_trees=show_trees) |
2744 | + def _qbrz_run(self, locations_list=None, ui_mode=False, no_graph=False, show_trees=False): |
2745 | + window = LogWindow(locations_list, None, None, ui_mode=ui_mode, no_graph=no_graph, show_trees=show_trees) |
2746 | window.show() |
2747 | self._application.exec_() |
2748 | |
2749 | @@ -541,17 +519,14 @@ |
2750 | |
2751 | takes_options = [ |
2752 | 'revision', |
2753 | - Option('encoding', type=check_encoding, |
2754 | - help='Encoding of files content (default: utf-8).'), |
2755 | - Option('native', |
2756 | - help='Show file with native application.'), |
2757 | + Option('encoding', type=check_encoding, help='Encoding of files content (default: utf-8).'), |
2758 | + Option('native', help='Show file with native application.'), |
2759 | ] |
2760 | takes_args = ['filename'] |
2761 | |
2762 | def _qbrz_run(self, filename, revision=None, encoding=None, native=None): |
2763 | if revision is not None and len(revision) != 1: |
2764 | - raise errors.BzrCommandError("bzr qcat --revision takes exactly" |
2765 | - " one revision specifier") |
2766 | + raise errors.BzrCommandError("brz qcat --revision takes exactly one revision specifier") |
2767 | |
2768 | if native: |
2769 | branch, relpath = Branch.open_containing(filename) |
2770 | @@ -563,9 +538,7 @@ |
2771 | result = cat_to_native_app(tree, relpath) |
2772 | return int(not result) |
2773 | |
2774 | - |
2775 | - window = QBzrCatWindow(filename = filename, revision = revision, |
2776 | - encoding = encoding) |
2777 | + window = QBzrCatWindow(filename = filename, revision = revision, encoding = encoding) |
2778 | window.show() |
2779 | self._application.exec_() |
2780 | |
2781 | @@ -576,7 +549,7 @@ |
2782 | takes_options = [ |
2783 | 'remember', 'overwrite', |
2784 | simple_revision_option, |
2785 | - bzr_option('pull', 'directory'), |
2786 | + brz_option('pull', 'directory'), |
2787 | ui_mode_option, |
2788 | ] |
2789 | takes_args = ['location?'] |
2790 | @@ -605,9 +578,9 @@ |
2791 | |
2792 | takes_options = [ui_mode_option, |
2793 | simple_revision_option, |
2794 | - bzr_option('merge', 'directory'), |
2795 | - bzr_option('merge', 'force'), |
2796 | - bzr_option('merge', 'uncommitted'), |
2797 | + brz_option('merge', 'directory'), |
2798 | + brz_option('merge', 'force'), |
2799 | + brz_option('merge', 'uncommitted'), |
2800 | 'remember'] |
2801 | takes_args = ['location?'] |
2802 | |
2803 | @@ -632,9 +605,9 @@ |
2804 | """Update a mirror of this branch.""" |
2805 | |
2806 | takes_options = ['remember', 'overwrite', |
2807 | - bzr_option("push", "create-prefix"), |
2808 | - bzr_option("push", "use-existing-dir"), |
2809 | - bzr_option("push", "directory"), |
2810 | + brz_option("push", "create-prefix"), |
2811 | + brz_option("push", "use-existing-dir"), |
2812 | + brz_option("push", "directory"), |
2813 | ui_mode_option] |
2814 | takes_args = ['location?'] |
2815 | |
2816 | @@ -669,7 +642,7 @@ |
2817 | takes_options = [simple_revision_option, |
2818 | ui_mode_option] |
2819 | try: |
2820 | - takes_options.append(bzr_option("branch", "bind")) |
2821 | + takes_options.append(brz_option("branch", "bind")) |
2822 | except KeyError: |
2823 | # older version of bzr that doesn't support the option |
2824 | pass |
2825 | @@ -704,19 +677,17 @@ |
2826 | ' acceptable for verification.', |
2827 | short_name='k', |
2828 | type=str,), |
2829 | - 'revision', |
2830 | + 'revision', |
2831 | ] |
2832 | takes_args = ['location?'] |
2833 | |
2834 | def _qbrz_run(self, acceptable_keys=None, revision=None, location=CUR_DIR): |
2835 | if gpg.GPGStrategy.verify_signatures_available(): |
2836 | - window = QBzrVerifySignaturesWindow(acceptable_keys, revision, |
2837 | - location) |
2838 | + window = QBzrVerifySignaturesWindow(acceptable_keys, revision, location) |
2839 | window.show() |
2840 | self._application.exec_() |
2841 | else: |
2842 | - raise errors.DependencyNotPresent("python-gpgme", |
2843 | - "python-gpgme not installed") |
2844 | + raise errors.DependencyNotPresent("python-gpgme", "python-gpgme not installed") |
2845 | |
2846 | class cmd_qinit(QBzrCommand): |
2847 | """Initializes a new branch or shared repository.""" |
2848 | @@ -734,11 +705,8 @@ |
2849 | __doc__ = breezy.builtins.cmd_merge.__doc__ |
2850 | |
2851 | takes_options = breezy.builtins.cmd_merge.takes_options + [ |
2852 | - Option('qpreview', help='Instead of merging, ' |
2853 | - 'show a diff of the merge in a GUI window.'), |
2854 | - Option('encoding', type=check_encoding, |
2855 | - help='Encoding of files content, used with --qpreview ' |
2856 | - '(default: utf-8).'), |
2857 | + Option('qpreview', help='Instead of merging, show a diff of the merge in a GUI window.'), |
2858 | + Option('encoding', type=check_encoding, help='Encoding of files content, used with --qpreview (default: utf-8).'), |
2859 | ] |
2860 | |
2861 | def run(self, *args, **kw): |
2862 | @@ -865,7 +833,6 @@ |
2863 | self.main_window.show() |
2864 | self._application.exec_() |
2865 | |
2866 | - |
2867 | class cmd_qhelp(QBzrCommand): |
2868 | """Shows a help window""" |
2869 | |
2870 | @@ -885,9 +852,9 @@ |
2871 | takes_args = ['tag_name?'] |
2872 | takes_options = [ |
2873 | ui_mode_option, |
2874 | - bzr_option('tag', 'delete'), |
2875 | - bzr_option('tag', 'directory'), |
2876 | - bzr_option('tag', 'force'), |
2877 | + brz_option('tag', 'delete'), |
2878 | + brz_option('tag', 'directory'), |
2879 | + brz_option('tag', 'force'), |
2880 | 'revision', |
2881 | ] |
2882 | |
2883 | @@ -997,7 +964,7 @@ |
2884 | from breezy.plugins.qbrz.lib.switch import QBzrSwitchWindow |
2885 | |
2886 | branch = Branch.open_containing(CUR_DIR)[0] |
2887 | - contrldir = ControlDir.open_containing(CUR_DIR)[0] |
2888 | + controldir = ControlDir.open_containing(CUR_DIR)[0] |
2889 | self.main_window = QBzrSwitchWindow(branch, controldir, location, ui_mode) |
2890 | self.main_window.show() |
2891 | self._application.exec_() |
2892 | @@ -1078,11 +1045,11 @@ |
2893 | Option('directory', |
2894 | help='Working directory.', |
2895 | short_name='d', |
2896 | - type=unicode, |
2897 | + type=str, |
2898 | ), |
2899 | Option('category', |
2900 | help='Initial category selection.', |
2901 | - type=unicode, |
2902 | + type=str, |
2903 | ), |
2904 | execute_option, |
2905 | ] |
2906 | @@ -1106,15 +1073,15 @@ |
2907 | execute=execute) |
2908 | window.show() |
2909 | self._application.exec_() |
2910 | - |
2911 | + |
2912 | class cmd_qshelve(QBzrCommand): |
2913 | """Shelve selected changes away.""" |
2914 | takes_args = ['file*'] |
2915 | takes_options = [ |
2916 | ui_mode_option, |
2917 | - bzr_option('shelve', 'list'), |
2918 | - bzr_option('shelve', 'directory'), |
2919 | - bzr_option('shelve', 'message'), |
2920 | + brz_option('shelve', 'list'), |
2921 | + brz_option('shelve', 'directory'), |
2922 | + brz_option('shelve', 'message'), |
2923 | Option('all', help='Select all changes.'), |
2924 | Option('complete', help='Show complete files.'), |
2925 | Option('ignore-whitespace', short_name='w', |
2926 | @@ -1123,7 +1090,7 @@ |
2927 | help='Encoding of files content (default: utf-8).'), |
2928 | ] |
2929 | |
2930 | - def _qbrz_run(self, file_list=None, list=False, directory=None, ui_mode=False, |
2931 | + def _qbrz_run(self, file_list=None, list=False, directory=None, ui_mode=False, |
2932 | complete=False, ignore_whitespace=False, encoding=None, |
2933 | all=False, message=None): |
2934 | if list: |
2935 | @@ -1131,7 +1098,7 @@ |
2936 | else: |
2937 | initial_tab = 0 |
2938 | self.main_window = ShelveWindow(file_list=file_list, directory=directory, ui_mode=ui_mode, |
2939 | - initial_tab=initial_tab, complete=complete, |
2940 | + initial_tab=initial_tab, complete=complete, |
2941 | ignore_whitespace=ignore_whitespace, encoding=encoding, |
2942 | select_all=all, message=message) |
2943 | self.main_window.show() |
2944 | @@ -1141,7 +1108,7 @@ |
2945 | """Restore shalved changes.""" |
2946 | takes_options = [ |
2947 | ui_mode_option, |
2948 | - bzr_option('unshelve', 'directory'), |
2949 | + brz_option('unshelve', 'directory'), |
2950 | Option('complete', help='Show complete files.'), |
2951 | Option('ignore-whitespace', short_name='w', |
2952 | help="Ignore whitespace when finding differences.(Only work when --list specified)"), |
2953 | @@ -1149,10 +1116,10 @@ |
2954 | help='Encoding of files content (default: utf-8).'), |
2955 | ] |
2956 | |
2957 | - def _qbrz_run(self, directory=None, ui_mode=False, |
2958 | + def _qbrz_run(self, directory=None, ui_mode=False, |
2959 | complete=False, ignore_whitespace=False, encoding=None): |
2960 | self.main_window = ShelveWindow(directory=directory, ui_mode=ui_mode, |
2961 | - initial_tab=1, complete=complete, |
2962 | + initial_tab=1, complete=complete, |
2963 | ignore_whitespace=ignore_whitespace, encoding=encoding) |
2964 | self.main_window.show() |
2965 | self._application.exec_() |
2966 | @@ -1163,7 +1130,7 @@ |
2967 | takes_args = [] |
2968 | takes_options = [ |
2969 | ui_mode_option, |
2970 | - bzr_option('ignore', 'directory'), |
2971 | + brz_option('ignore', 'directory'), |
2972 | ] |
2973 | aliases = [] |
2974 | |
2975 | |
2976 | === modified file 'lib/commit.py' |
2977 | --- lib/commit.py 2017-09-11 06:53:22 +0000 |
2978 | +++ lib/commit.py 2020-07-16 14:28:25 +0000 |
2979 | @@ -69,9 +69,11 @@ |
2980 | |
2981 | def __init__(self, spell_checker, parent=None, main_window=None): |
2982 | QtGui.QTextEdit.__init__(self, parent) |
2983 | + # RJL The completer, I think, is to provide suggestions for anything typed |
2984 | self.completer = None |
2985 | self.spell_checker = spell_checker |
2986 | - self.eow = QtCore.QString("~!@#$%^&*()_+{}|:\"<>?,./;'[]\\-=") |
2987 | + # RJL eow = 'end of word'? |
2988 | + self.eow = "~!@#$%^&*()_+{}|:\"<>?,./;'[]\\-=" |
2989 | self.main_window = main_window |
2990 | |
2991 | def inputMethodEvent(self, e): |
2992 | @@ -98,15 +100,25 @@ |
2993 | QtGui.QTextEdit.keyPressEvent(self, e) |
2994 | |
2995 | ctrlOrShift = e.modifiers() & (QtCore.Qt.ControlModifier | QtCore.Qt.ShiftModifier) |
2996 | - if ctrlOrShift and e.text().isEmpty(): |
2997 | + # if ctrlOrShift and e.text().isEmpty(): |
2998 | + if ctrlOrShift and not e.text(): |
2999 | return |
3000 | |
3001 | hasModifier = (e.modifiers() != QtCore.Qt.NoModifier) and not ctrlOrShift |
3002 | completionPrefix = self.textUnderCursor() |
3003 | |
3004 | - if not isShortcut and (hasModifier or e.text().isEmpty() |
3005 | - or completionPrefix.length() < 2 |
3006 | - or self.eow.contains(e.text().right(1))): |
3007 | + # RJL I *think* this is trying to find out whether to hide or display a list |
3008 | + # of possible completions. right() is a QString method that: |
3009 | + # |
3010 | + # Returns a substring that contains the n rightmost characters of the string. |
3011 | + # The entire string is returned if n is greater than size() or less than zero. |
3012 | + # QString x = "Pineapple"; |
3013 | + # QString y = x.right(5); // y == "apple" |
3014 | + # |
3015 | + # or simply x[-5:] in the land of Python, .right(1) is the last letter |
3016 | + # which is e.text()[-1:] |
3017 | + |
3018 | + if not isShortcut and (hasModifier or not e.text() or len(completionPrefix) < 2 or e.text()[-1:] in self.eow): |
3019 | c.popup().hide() |
3020 | return |
3021 | |
3022 | @@ -115,8 +127,7 @@ |
3023 | c.popup().setCurrentIndex(c.completionModel().index(0, 0)) |
3024 | |
3025 | cr = self.cursorRect() |
3026 | - cr.setWidth(c.popup().sizeHintForColumn(0) + |
3027 | - c.popup().verticalScrollBar().sizeHint().width()) |
3028 | + cr.setWidth(c.popup().sizeHintForColumn(0) + c.popup().verticalScrollBar().sizeHint().width()) |
3029 | c.complete(cr); |
3030 | |
3031 | def textUnderCursor(self): |
3032 | @@ -126,41 +137,40 @@ |
3033 | |
3034 | def insertCompletion(self, completion): |
3035 | tc = self.textCursor() |
3036 | - extra = completion.length() - self.completer.completionPrefix().length() |
3037 | + extra = len(completion) - len(self.completer.completionPrefix()) |
3038 | tc.movePosition(QtGui.QTextCursor.Left) |
3039 | tc.movePosition(QtGui.QTextCursor.EndOfWord) |
3040 | - tc.insertText(completion.right(extra)) |
3041 | + # We want the right-most 'extra' letters |
3042 | + # tc.insertText(completion.right(extra)) |
3043 | + tc.insertText(completion[-extra:]) |
3044 | self.setTextCursor(tc) |
3045 | |
3046 | def setCompleter(self, completer): |
3047 | self.completer = completer |
3048 | completer.setWidget(self) |
3049 | completer.setCaseSensitivity(QtCore.Qt.CaseSensitive) |
3050 | - self.connect(completer, QtCore.SIGNAL("activated(QString)"), |
3051 | - self.insertCompletion) |
3052 | + self.connect(completer, QtCore.SIGNAL("activated(QString)"), self.insertCompletion) |
3053 | |
3054 | def contextMenuEvent(self, event): |
3055 | menu = self.createStandardContextMenu(event.globalPos()) |
3056 | - |
3057 | + |
3058 | self.context_tc = self.cursorForPosition(event.pos()) |
3059 | self.context_tc.movePosition(QtGui.QTextCursor.StartOfWord) |
3060 | - self.context_tc.movePosition(QtGui.QTextCursor.EndOfWord, |
3061 | - QtGui.QTextCursor.KeepAnchor) |
3062 | - text = unicode(self.context_tc.selectedText()) |
3063 | + self.context_tc.movePosition(QtGui.QTextCursor.EndOfWord, QtGui.QTextCursor.KeepAnchor) |
3064 | + text = str(self.context_tc.selectedText()) |
3065 | if list(self.spell_checker.check(text)): |
3066 | suggestions = self.spell_checker.suggest(text) |
3067 | first_action = menu.actions()[0] |
3068 | for suggestion in suggestions: |
3069 | action = QtGui.QAction(suggestion, self) |
3070 | - self.connect(action, QtCore.SIGNAL("triggered(bool)"), |
3071 | - self.suggestion_selected(suggestion)) |
3072 | + self.connect(action, QtCore.SIGNAL("triggered(bool)"), self.suggestion_selected(suggestion)) |
3073 | menu.insertAction(first_action, action) |
3074 | if suggestions: |
3075 | menu.insertSeparator(first_action) |
3076 | - |
3077 | + |
3078 | menu.exec_(event.globalPos()) |
3079 | event.accept() |
3080 | - |
3081 | + |
3082 | def suggestion_selected(self, text): |
3083 | def _suggestion_selected(b): |
3084 | self.context_tc.insertText(text); |
3085 | @@ -175,12 +185,12 @@ |
3086 | # that is going to make this much slower. |
3087 | self.header().hideSection(0) |
3088 | self.log_model.last_rev_is_placeholder = True |
3089 | - |
3090 | + |
3091 | def load_tree(self, tree): |
3092 | bi = BranchInfo('', tree, tree.branch) |
3093 | self.log_model.load( |
3094 | (bi,), bi, None, False, logmodel.PendingMergesGraphVizLoader) |
3095 | - |
3096 | + |
3097 | def create_context_menu(self, file_ids): |
3098 | super(PendingMergesList, self).create_context_menu(file_ids) |
3099 | showinfo = QtGui.QAction("Show &information...", self) |
3100 | @@ -196,19 +206,19 @@ |
3101 | |
3102 | def default_action(self, index=None): |
3103 | """Show information of a single revision from a index.""" |
3104 | - |
3105 | + |
3106 | if index is None: |
3107 | index = self.currentIndex() |
3108 | - |
3109 | + |
3110 | # XXX We should make this show all selected revisions... |
3111 | - |
3112 | - revid = str(index.data(logmodel.RevIdRole).toString()) |
3113 | + |
3114 | + revid = index.data(logmodel.RevIdRole) |
3115 | branch = self.log_model.graph_viz.get_revid_branch(revid) |
3116 | parent_window = self.window() |
3117 | window = RevisionView(revid, branch, parent=parent_window) |
3118 | window.show() |
3119 | parent_window.windows.append(window) |
3120 | - |
3121 | + |
3122 | |
3123 | class CommitWindow(SubProcessDialog): |
3124 | |
3125 | @@ -230,10 +240,10 @@ |
3126 | |
3127 | self.is_bound = bool(tree.branch.get_bound_location()) |
3128 | self.has_pending_merges = len(tree.get_parent_ids())>1 |
3129 | - |
3130 | + |
3131 | if self.has_pending_merges and selected_list: |
3132 | raise errors.CannotCommitSelectedFileMerge(selected_list) |
3133 | - |
3134 | + |
3135 | self.windows = [] |
3136 | self.initial_selected_list = selected_list |
3137 | |
3138 | @@ -274,7 +284,7 @@ |
3139 | if local: |
3140 | self.local_checkbox.setChecked(True) |
3141 | self.update_branch_groupbox() |
3142 | - |
3143 | + |
3144 | self.not_uptodate_errors = { |
3145 | 'BoundBranchOutOfDate': gettext( |
3146 | 'Local branch is out of date with master branch.\n' |
3147 | @@ -285,25 +295,25 @@ |
3148 | } |
3149 | self.not_uptodate_info = InfoWidget(branch_groupbox) |
3150 | not_uptodate_layout = QtGui.QHBoxLayout(self.not_uptodate_info) |
3151 | - |
3152 | + |
3153 | # XXX this is to big. Resize |
3154 | not_uptodate_icon = QtGui.QLabel() |
3155 | not_uptodate_icon.setPixmap(self.style().standardPixmap( |
3156 | QtGui.QStyle.SP_MessageBoxWarning)) |
3157 | not_uptodate_layout.addWidget(not_uptodate_icon) |
3158 | - |
3159 | + |
3160 | self.not_uptodate_label = QtGui.QLabel('error message goes here') |
3161 | not_uptodate_layout.addWidget(self.not_uptodate_label, 2) |
3162 | - |
3163 | + |
3164 | update_button = QtGui.QPushButton(gettext('Update')) |
3165 | self.connect(update_button, QtCore.SIGNAL("clicked(bool)"), |
3166 | self.open_update_win) |
3167 | |
3168 | not_uptodate_layout.addWidget(update_button) |
3169 | - |
3170 | + |
3171 | self.not_uptodate_info.hide() |
3172 | branch_layout.addWidget(self.not_uptodate_info, 3, 0, 1, 2) |
3173 | - |
3174 | + |
3175 | splitter = QtGui.QSplitter(QtCore.Qt.Vertical, self) |
3176 | |
3177 | message_groupbox = QtGui.QGroupBox(gettext("Message"), splitter) |
3178 | @@ -323,24 +333,24 @@ |
3179 | else: |
3180 | self.show_nonversioned_checkbox.setChecked(QtCore.Qt.Unchecked) |
3181 | |
3182 | - self.filelist = TreeWidget(self) |
3183 | - self.filelist.throbber = self.throbber |
3184 | + self.filelist_widget = TreeWidget(self) |
3185 | + self.filelist_widget.throbber = self.throbber |
3186 | if show_nonversioned: |
3187 | - self.filelist.tree_model.set_select_all_kind('all') |
3188 | + self.filelist_widget.tree_model.set_select_all_kind('all') |
3189 | else: |
3190 | - self.filelist.tree_model.set_select_all_kind('versioned') |
3191 | - |
3192 | + self.filelist_widget.tree_model.set_select_all_kind('versioned') |
3193 | + |
3194 | self.file_words = {} |
3195 | - self.connect(self.filelist.tree_model, |
3196 | + self.connect(self.filelist_widget.tree_model, |
3197 | QtCore.SIGNAL("dataChanged(QModelIndex, QModelIndex)"), |
3198 | self.on_filelist_data_changed) |
3199 | - |
3200 | - self.selectall_checkbox = SelectAllCheckBox(self.filelist, self) |
3201 | + |
3202 | + self.selectall_checkbox = SelectAllCheckBox(self.filelist_widget, self) |
3203 | self.selectall_checkbox.setCheckState(QtCore.Qt.Checked) |
3204 | |
3205 | language = get_global_config().get_user_option('spellcheck_language') or 'en' |
3206 | spell_checker = SpellChecker(language) |
3207 | - |
3208 | + |
3209 | # Equivalent for 'bzr commit --message' |
3210 | self.message = TextEdit(spell_checker, message_groupbox, main_window=self) |
3211 | self.message.setToolTip(gettext("Enter the commit message")) |
3212 | @@ -393,10 +403,10 @@ |
3213 | self.tabWidget.addTab(files_tab, gettext("Changes")) |
3214 | |
3215 | vbox = QtGui.QVBoxLayout(files_tab) |
3216 | - vbox.addWidget(self.filelist) |
3217 | + vbox.addWidget(self.filelist_widget) |
3218 | self.connect(self.show_nonversioned_checkbox, QtCore.SIGNAL("toggled(bool)"), self.show_nonversioned) |
3219 | vbox.addWidget(self.show_nonversioned_checkbox) |
3220 | - |
3221 | + |
3222 | vbox.addWidget(self.selectall_checkbox) |
3223 | |
3224 | # Display a list of pending merges |
3225 | @@ -405,11 +415,11 @@ |
3226 | self.selectall_checkbox.setEnabled(False) |
3227 | self.pending_merges_list = PendingMergesList( |
3228 | self.processEvents, self.throbber, self) |
3229 | - |
3230 | + |
3231 | self.tabWidget.addTab(self.pending_merges_list, |
3232 | gettext("Pending Merges")) |
3233 | self.tabWidget.setCurrentWidget(self.pending_merges_list) |
3234 | - |
3235 | + |
3236 | # Pending-merge widget gets disabled as we are executing. |
3237 | QtCore.QObject.connect(self, |
3238 | QtCore.SIGNAL("disableUi(bool)"), |
3239 | @@ -460,7 +470,7 @@ |
3240 | |
3241 | # Try to be smart: if there is no saved message |
3242 | # then set focus on Edit Area; otherwise on OK button. |
3243 | - if unicode(self.message.toPlainText()).strip(): |
3244 | + if str(self.message.toPlainText()).strip(): |
3245 | self.buttonbox.setFocus() |
3246 | else: |
3247 | self.message.setFocus() |
3248 | @@ -490,15 +500,15 @@ |
3249 | # loading the file list. |
3250 | self.pending_merges_list._load_visible_revisions() |
3251 | self.processEvents() |
3252 | - |
3253 | - self.filelist.tree_model.checkable = not self.pending_merges_list |
3254 | + |
3255 | + self.filelist_widget.tree_model.checkable = not self.pending_merges_list |
3256 | self.is_loading = True |
3257 | # XXX Would be nice if we could only load the files when the |
3258 | # user clicks on the changes tab, but that would mean that |
3259 | # we can't load the words list. |
3260 | if not refresh: |
3261 | - fmodel = self.filelist.tree_filter_model |
3262 | - |
3263 | + fmodel = self.filelist_widget.tree_filter_model |
3264 | + |
3265 | want_unversioned = self.show_nonversioned_checkbox.isChecked() |
3266 | fmodel.setFilter(fmodel.UNVERSIONED, want_unversioned) |
3267 | if not want_unversioned and self.initial_selected_list: |
3268 | @@ -508,8 +518,8 @@ |
3269 | if not self.tree.path2id(path): |
3270 | want_unversioned = True |
3271 | break |
3272 | - |
3273 | - self.filelist.set_tree( |
3274 | + |
3275 | + self.filelist_widget.set_tree( |
3276 | self.tree, |
3277 | branch=self.tree.branch, |
3278 | changes_mode=True, |
3279 | @@ -517,7 +527,7 @@ |
3280 | initial_checked_paths=self.initial_selected_list, |
3281 | change_load_filter=lambda c:not c.is_ignored()) |
3282 | else: |
3283 | - self.filelist.refresh() |
3284 | + self.filelist_widget.refresh() |
3285 | self.is_loading = False |
3286 | self.processEvents() |
3287 | self.update_compleater_words() |
3288 | @@ -526,28 +536,28 @@ |
3289 | finally: |
3290 | self.throbber.hide() |
3291 | self.refresh_button.setDisabled(False) |
3292 | - |
3293 | + |
3294 | def refresh(self): |
3295 | self.load(True) |
3296 | |
3297 | def on_filelist_data_changed(self, start_index, end_index): |
3298 | self.update_compleater_words() |
3299 | - |
3300 | + |
3301 | def update_compleater_words(self): |
3302 | if self.is_loading: |
3303 | return |
3304 | - |
3305 | + |
3306 | num_files_loaded = 0 |
3307 | - |
3308 | + |
3309 | words = set() |
3310 | - for ref in self.filelist.tree_model.iter_checked(): |
3311 | + for ref in self.filelist_widget.tree_model.iter_checked(): |
3312 | path = ref.path |
3313 | if path not in self.file_words: |
3314 | file_words = set() |
3315 | if num_files_loaded < MAX_AUTOCOMPLETE_FILES: |
3316 | file_words.add(path) |
3317 | file_words.add(os.path.split(path)[-1]) |
3318 | - change = self.filelist.tree_model.inventory_data_by_path[ |
3319 | + change = self.filelist_widget.tree_model.inventory_data_by_path[ |
3320 | ref.path].change |
3321 | if change and change.is_renamed(): |
3322 | file_words.add(change.oldpath()) |
3323 | @@ -571,7 +581,7 @@ |
3324 | words = list(words) |
3325 | words.sort(key=lambda x: x.lower()) |
3326 | self.completer_model.setStringList(words) |
3327 | - |
3328 | + |
3329 | def enableBugs(self, state): |
3330 | if state == QtCore.Qt.Checked: |
3331 | self.bugs.setEnabled(True) |
3332 | @@ -608,12 +618,12 @@ |
3333 | return |
3334 | # collect data |
3335 | ci_data = QBzrCommitData(tree=self.tree) |
3336 | - message = unicode(self.message.toPlainText()).strip() |
3337 | + message = str(self.message.toPlainText()).strip() |
3338 | if message: |
3339 | ci_data['message'] = message |
3340 | bug_str = '' |
3341 | if self.bugsCheckBox.isChecked(): |
3342 | - bug_str = unicode(self.bugs.text()).strip() |
3343 | + bug_str = str(self.bugs.text()).strip() |
3344 | if bug_str: |
3345 | ci_data['bugs'] = bug_str |
3346 | # save only if data different |
3347 | @@ -630,7 +640,7 @@ |
3348 | self.ci_data.wipe() |
3349 | |
3350 | def _get_message(self): |
3351 | - return unicode(self.message.toPlainText()).strip() |
3352 | + return str(self.message.toPlainText()).strip() |
3353 | |
3354 | def _get_selected_files(self): |
3355 | """Return (has_files_to_commit[bool], files_to_commit[list], files_to_add[list])""" |
3356 | @@ -639,7 +649,7 @@ |
3357 | |
3358 | files_to_commit = [] |
3359 | files_to_add = [] |
3360 | - for ref in self.filelist.tree_model.iter_checked(): |
3361 | + for ref in self.filelist_widget.tree_model.iter_checked(): |
3362 | if ref.file_id is None: |
3363 | files_to_add.append(ref.path) |
3364 | files_to_commit.append(ref.path) |
3365 | @@ -679,15 +689,15 @@ |
3366 | args.extend(files_to_commit) |
3367 | |
3368 | if self.bugsCheckBox.isChecked(): |
3369 | - for s in unicode(self.bugs.text()).split(): |
3370 | + for s in str(self.bugs.text()).split(): |
3371 | args.append(("--fixes=%s" % s)) |
3372 | - |
3373 | + |
3374 | if self.authorCheckBox.isChecked(): |
3375 | - args.append(("--author=%s" % unicode(self.author.text()))) |
3376 | - |
3377 | + args.append(("--author=%s" % str(self.author.text()))) |
3378 | + |
3379 | if self.is_bound and self.local_checkbox.isChecked(): |
3380 | args.append("--local") |
3381 | - |
3382 | + |
3383 | dir = self.tree.basedir |
3384 | commands = [] |
3385 | if files_to_add: |
3386 | @@ -699,19 +709,19 @@ |
3387 | |
3388 | def show_nonversioned(self, state): |
3389 | """Show/hide non-versioned files.""" |
3390 | - if state and not self.filelist.want_unversioned: |
3391 | - state = self.filelist.get_state() |
3392 | - self.filelist.set_tree( |
3393 | + if state and not self.filelist_widget.want_unversioned: |
3394 | + state = self.filelist_widget.get_state() |
3395 | + self.filelist_widget.set_tree( |
3396 | self.tree, changes_mode=True, want_unversioned=True, |
3397 | change_load_filter=lambda c:not c.is_ignored()) |
3398 | - self.filelist.restore_state(state) |
3399 | - |
3400 | + self.filelist_widget.restore_state(state) |
3401 | + |
3402 | if state: |
3403 | - self.filelist.tree_model.set_select_all_kind('all') |
3404 | + self.filelist_widget.tree_model.set_select_all_kind('all') |
3405 | else: |
3406 | - self.filelist.tree_model.set_select_all_kind('versioned') |
3407 | - |
3408 | - fmodel = self.filelist.tree_filter_model |
3409 | + self.filelist_widget.tree_model.set_select_all_kind('versioned') |
3410 | + |
3411 | + fmodel = self.filelist_widget.tree_filter_model |
3412 | fmodel.setFilter(fmodel.UNVERSIONED, state) |
3413 | |
3414 | def _save_or_wipe_commit_data(self): |
3415 | @@ -756,47 +766,43 @@ |
3416 | @param dialog_action: purpose of parent window (main action) |
3417 | """ |
3418 | # XXX make this function universal for both qcommit and qrevert (?) |
3419 | - if self.filelist.tree_model.checkable: |
3420 | + if self.filelist_widget.tree_model.checkable: |
3421 | checked = [] # checked versioned |
3422 | unversioned = [] # checked unversioned (supposed to be added) |
3423 | - for ref in self.filelist.tree_model.iter_checked(): |
3424 | + for ref in self.filelist_widget.tree_model.iter_checked(): |
3425 | if ref.file_id: |
3426 | checked.append(ref.path) |
3427 | else: |
3428 | unversioned.append(ref.path) |
3429 | - |
3430 | + |
3431 | if checked: |
3432 | arg_provider = InternalWTDiffArgProvider( |
3433 | self.tree.basis_tree().get_revision_id(), self.tree, |
3434 | self.tree.branch, self.tree.branch, |
3435 | specific_files=checked) |
3436 | - |
3437 | - show_diff(arg_provider, ext_diff=ext_diff, parent_window=self, |
3438 | - context=self.filelist.diff_context) |
3439 | + |
3440 | + show_diff(arg_provider, ext_diff=ext_diff, parent_window=self, context=self.filelist_widget.diff_context) |
3441 | else: |
3442 | msg = "No changes selected to " + dialog_action |
3443 | - QtGui.QMessageBox.warning(self, |
3444 | - "QBzr - " + gettext("Diff"), |
3445 | - gettext(msg), |
3446 | - QtGui.QMessageBox.Ok) |
3447 | - |
3448 | + QtGui.QMessageBox.warning(self, "QBrz - " + gettext("Diff"), gettext(msg), QtGui.QMessageBox.Ok) |
3449 | + |
3450 | if unversioned: |
3451 | # XXX show infobox with message that not all files shown in diff |
3452 | pass |
3453 | else: |
3454 | arg_provider = InternalWTDiffArgProvider( |
3455 | self.tree.basis_tree().get_revision_id(), self.tree, |
3456 | - self.tree.branch, self.tree.branch) |
3457 | + self.tree.branch, self.tree.branch) |
3458 | show_diff(arg_provider, ext_diff=ext_diff, parent_window=self, |
3459 | - context=self.filelist.diff_context) |
3460 | - |
3461 | + context=self.filelist_widget.diff_context) |
3462 | + |
3463 | def on_failed(self, error): |
3464 | SubProcessDialog.on_failed(self, error) |
3465 | error = str(error) |
3466 | if error in self.not_uptodate_errors: |
3467 | self.not_uptodate_label.setText(self.not_uptodate_errors[error]) |
3468 | self.not_uptodate_info.show() |
3469 | - |
3470 | + |
3471 | def open_update_win(self, b): |
3472 | update_window = QBzrUpdateWindow(self.tree) |
3473 | self.windows.append(update_window) |
3474 | @@ -804,4 +810,4 @@ |
3475 | QtCore.QObject.connect(update_window, |
3476 | QtCore.SIGNAL("subprocessFinished(bool)"), |
3477 | self.not_uptodate_info, |
3478 | - QtCore.SLOT("setHidden(bool)")) |
3479 | + QtCore.SLOT("setHidden(bool)")) |
3480 | |
3481 | === modified file 'lib/commit_data.py' |
3482 | --- lib/commit_data.py 2017-09-11 06:53:22 +0000 |
3483 | +++ lib/commit_data.py 2020-07-16 14:28:25 +0000 |
3484 | @@ -64,12 +64,12 @@ |
3485 | string or None). |
3486 | """ |
3487 | d = {} |
3488 | - for k,v in self._data.iteritems(): |
3489 | + for k,v in self._data.items(): |
3490 | if v not in (None, ''): |
3491 | d[k] = v |
3492 | return d |
3493 | |
3494 | - def __nonzero__(self): |
3495 | + def __bool__(self): |
3496 | """Check if there is some data actually. |
3497 | @return: True if data dictionary is not empty. |
3498 | """ |
3499 | @@ -92,7 +92,7 @@ |
3500 | |
3501 | def keys(self): |
3502 | """Return keys of internal dict.""" |
3503 | - return self._data.keys() |
3504 | + return list(self._data.keys()) |
3505 | |
3506 | def as_dict(self): |
3507 | return self._data.copy() |
3508 | @@ -104,7 +104,7 @@ |
3509 | """ |
3510 | if data: |
3511 | self._data.update(data) |
3512 | - for key, value in kw.iteritems(): |
3513 | + for key, value in kw.items(): |
3514 | self._data[key] = value |
3515 | |
3516 | def set_data_on_uncommit(self, old_revid, new_revid): |
3517 | @@ -137,7 +137,7 @@ |
3518 | instance. |
3519 | """ |
3520 | try: |
3521 | - for k,v in self._data.iteritems(): |
3522 | + for k,v in self._data.items(): |
3523 | if v != other[k]: |
3524 | return False |
3525 | except KeyError: |
3526 | |
3527 | === modified file 'lib/conditional_dataview.py' |
3528 | --- lib/conditional_dataview.py 2009-08-18 14:27:46 +0000 |
3529 | +++ lib/conditional_dataview.py 2020-07-16 14:28:25 +0000 |
3530 | @@ -16,7 +16,7 @@ |
3531 | |
3532 | |
3533 | from PyQt4 import QtGui |
3534 | -from PyQt4.QtCore import Qt, QVariant |
3535 | +from PyQt4.QtCore import Qt |
3536 | |
3537 | |
3538 | class QBzrConditionalDataView(QtGui.QFrame): |
3539 | @@ -113,11 +113,11 @@ |
3540 | icon = decoration_provider(row, record) |
3541 | if icon: |
3542 | index = model.index(row, 0) |
3543 | - model.setData(index, QVariant(icon), Qt.DecorationRole) |
3544 | + model.setData(index, icon, Qt.DecorationRole) |
3545 | for col, value in enumerate(record): |
3546 | #print "putting %s into %d,%d" % (value, row, col) |
3547 | index = model.index(row, col) |
3548 | - model.setData(index, QVariant(value or ''), cell_role) |
3549 | + model.setData(index, value or '', cell_role) |
3550 | |
3551 | # Update the view & label |
3552 | self._view.setVisible(row_count > 0) |
3553 | |
3554 | === modified file 'lib/config.py' |
3555 | --- lib/config.py 2017-09-11 06:53:22 +0000 |
3556 | +++ lib/config.py 2020-07-16 14:28:25 +0000 |
3557 | @@ -20,10 +20,8 @@ |
3558 | import re |
3559 | import os.path |
3560 | from PyQt4 import QtCore, QtGui |
3561 | -from breezy.config import ( |
3562 | - ensure_config_dir_exists, |
3563 | - extract_email_address, |
3564 | - ) |
3565 | +from breezy.config import extract_email_address |
3566 | +from breezy.bedding import ensure_config_dir_exists |
3567 | from breezy import cmdline, errors, trace |
3568 | |
3569 | from breezy.plugins.qbrz.lib import ui_merge_config |
3570 | @@ -59,18 +57,17 @@ |
3571 | # XXX use special function from bugs.py instead |
3572 | _bug_tracker_re = re.compile('bugtracker_(.+?)_url') |
3573 | |
3574 | + |
3575 | class QRadioCheckItemDelegate(QtGui.QItemDelegate): |
3576 | - |
3577 | - def drawCheck (self, painter, option, rect, state): |
3578 | + |
3579 | + def drawCheck(self, painter, option, rect, state): |
3580 | style = self.parent().style() |
3581 | radioOption = QtGui.QStyleOptionButton() |
3582 | radioOption.rect = option.rect |
3583 | radioOption.state = option.state |
3584 | if state: |
3585 | radioOption.state = radioOption.state | QtGui.QStyle.State_On |
3586 | - style.drawControl(QtGui.QStyle.CE_RadioButton, |
3587 | - radioOption, |
3588 | - painter) |
3589 | + style.drawControl(QtGui.QStyle.CE_RadioButton, radioOption, painter) |
3590 | |
3591 | |
3592 | class QBzrConfigWindow(QBzrDialog): |
3593 | @@ -112,7 +109,7 @@ |
3594 | |
3595 | self.emailClientCombo = QtGui.QComboBox() |
3596 | for name, label in _mail_clients: |
3597 | - self.emailClientCombo.addItem(gettext(label), QtCore.QVariant(name)) |
3598 | + self.emailClientCombo.addItem(gettext(label), name) |
3599 | label = QtGui.QLabel(gettext("E-mail &client:")) |
3600 | label.setBuddy(self.emailClientCombo) |
3601 | generalGrid.addWidget(label, 3, 0) |
3602 | @@ -173,11 +170,11 @@ |
3603 | bugTrackersVBox = QtGui.QVBoxLayout(bugTrackersWidget) |
3604 | bugTrackersVBox.addWidget(self.bugTrackersList) |
3605 | bugTrackersVBox.addLayout(bugTrackersHBox) |
3606 | - |
3607 | + |
3608 | diffWidget = QtGui.QWidget() |
3609 | |
3610 | self.diffShowIntergroupColors = QtGui.QCheckBox(gettext("Show inter-group inserts and deletes in green and red"), diffWidget) |
3611 | - |
3612 | + |
3613 | label = QtGui.QLabel(gettext("External Diff Apps:")) |
3614 | self.extDiffList = QtGui.QTreeWidget(diffWidget) |
3615 | self.extDiffList.setRootIsDecorated(False) |
3616 | @@ -186,7 +183,7 @@ |
3617 | self.extDiffList.setItemDelegateForColumn(0, |
3618 | QRadioCheckItemDelegate(self.extDiffList)) |
3619 | self.connect(self.extDiffList, QtCore.SIGNAL("itemChanged (QTreeWidgetItem *,int)"), |
3620 | - self.extDiffListItemChanged) |
3621 | + self.extDiffListItemChanged) |
3622 | |
3623 | addExtDiffButton = QtGui.QPushButton(gettext("Add"), diffWidget) |
3624 | self.connect(addExtDiffButton, QtCore.SIGNAL("clicked()"), |
3625 | @@ -205,7 +202,7 @@ |
3626 | diffLayout.addWidget(label) |
3627 | diffLayout.addWidget(self.extDiffList) |
3628 | diffLayout.addLayout(extDiffButtonsLayout) |
3629 | - |
3630 | + |
3631 | if mergetools is not None: |
3632 | mergeWidget = QtGui.QWidget() |
3633 | self.merge_ui = ui_merge_config.Ui_MergeConfig() |
3634 | @@ -213,18 +210,18 @@ |
3635 | self.merge_ui.tools.sortByColumn(0, QtCore.Qt.AscendingOrder) |
3636 | self.merge_ui.remove.setEnabled(False) |
3637 | self.merge_ui.set_default.setEnabled(False) |
3638 | - |
3639 | + |
3640 | self.merge_tools_model = MergeToolsTableModel() |
3641 | self.merge_ui.tools.setModel(self.merge_tools_model) |
3642 | - |
3643 | + |
3644 | self.connect(self.merge_tools_model, |
3645 | QtCore.SIGNAL("dataChanged(QModelIndex,QModelIndex)"), |
3646 | self.merge_tools_data_changed) |
3647 | - |
3648 | + |
3649 | self.connect(self.merge_ui.tools.selectionModel(), |
3650 | QtCore.SIGNAL("selectionChanged(QItemSelection,QItemSelection)"), |
3651 | self.merge_tools_selectionChanged) |
3652 | - |
3653 | + |
3654 | self.connect(self.merge_ui.add, |
3655 | QtCore.SIGNAL("clicked()"), |
3656 | self.merge_tools_add_clicked) |
3657 | @@ -237,7 +234,7 @@ |
3658 | else: |
3659 | mergeWidget = QtGui.QLabel(gettext("Bazaar 2.4 or newer is required to configure mergetools.")) |
3660 | mergeWidget.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter) |
3661 | - |
3662 | + |
3663 | self.tabwidget.addTab(generalWidget, gettext("General")) |
3664 | self.tabwidget.addTab(aliasesWidget, gettext("Aliases")) |
3665 | self.tabwidget.addTab(bugTrackersWidget, gettext("Bug Trackers")) |
3666 | @@ -265,7 +262,7 @@ |
3667 | self.spellcheck_language_combo = QtGui.QComboBox() |
3668 | languages = sorted(SpellChecker.list_languages()) |
3669 | for name in languages: |
3670 | - self.spellcheck_language_combo.addItem(gettext(name), QtCore.QVariant(name)) |
3671 | + self.spellcheck_language_combo.addItem(gettext(name), name) |
3672 | if not languages: |
3673 | self.spellcheck_language_combo.setEnabled(False) |
3674 | label = QtGui.QLabel(gettext("Spell check &language:")) |
3675 | @@ -287,7 +284,7 @@ |
3676 | label.setBuddy(self.branchsourceBasedirEdit) |
3677 | grid.addWidget(label, 1, 0) |
3678 | grid.addLayout(branchsourceBasedirHBox, 1, 1) |
3679 | - |
3680 | + |
3681 | self.checkoutBasedirEdit = QtGui.QLineEdit() |
3682 | self.checkoutBasedirEdit.setToolTip(gettext("This directory will be automatically filled in your checkout destination input field")) |
3683 | btnCheckoutBasedirBrowse = QtGui.QPushButton(gettext('Browse...')) |
3684 | @@ -308,7 +305,7 @@ |
3685 | """Load the configuration.""" |
3686 | config = get_global_config() |
3687 | parser = config._get_parser() |
3688 | - |
3689 | + |
3690 | qconfig = get_qbrz_config() |
3691 | |
3692 | # Name & e-mail |
3693 | @@ -322,10 +319,10 @@ |
3694 | email = '' |
3695 | except errors.NoWhoami: |
3696 | name, email = get_user_id_from_os() |
3697 | - except Exception, e: |
3698 | + except Exception as e: |
3699 | trace.mutter("qconfig: load name/email error: %s", str(e)) |
3700 | name, email = '', '' |
3701 | - |
3702 | + |
3703 | self.nameEdit.setText(name) |
3704 | self.emailEdit.setText(email) |
3705 | |
3706 | @@ -337,8 +334,7 @@ |
3707 | # E-mail client |
3708 | mailClient = config.get_user_option('mail_client') |
3709 | if mailClient: |
3710 | - index = self.emailClientCombo.findData( |
3711 | - QtCore.QVariant(mailClient)) |
3712 | + index = self.emailClientCombo.findData(mailClient) |
3713 | if index >= 0: |
3714 | self.emailClientCombo.setCurrentIndex(index) |
3715 | |
3716 | @@ -348,8 +344,7 @@ |
3717 | # Spellcheck language |
3718 | spellcheck_language = config.get_user_option('spellcheck_language') or 'en' |
3719 | if spellcheck_language: |
3720 | - index = self.spellcheck_language_combo.findData( |
3721 | - QtCore.QVariant(spellcheck_language)) |
3722 | + index = self.spellcheck_language_combo.findData(spellcheck_language) |
3723 | if index >= 0: |
3724 | self.spellcheck_language_combo.setCurrentIndex(index) |
3725 | |
3726 | @@ -365,7 +360,7 @@ |
3727 | |
3728 | # Aliases |
3729 | aliases = parser.get('ALIASES', {}) |
3730 | - for alias, command in aliases.items(): |
3731 | + for alias, command in list(aliases.items()): |
3732 | item = QtGui.QTreeWidgetItem(self.aliasesList) |
3733 | item.setFlags(QtCore.Qt.ItemIsSelectable | |
3734 | QtCore.Qt.ItemIsEditable | |
3735 | @@ -375,7 +370,7 @@ |
3736 | |
3737 | # Bug trackers |
3738 | # XXX use special function from bugs.py |
3739 | - for name, value in parser.get('DEFAULT', {}).items(): |
3740 | + for name, value in list(parser.get('DEFAULT', {}).items()): |
3741 | m = _bug_tracker_re.match(name) |
3742 | if not m: |
3743 | continue |
3744 | @@ -386,7 +381,7 @@ |
3745 | QtCore.Qt.ItemIsEnabled) |
3746 | item.setText(0, abbreviation) |
3747 | item.setText(1, value) |
3748 | - |
3749 | + |
3750 | # Diff |
3751 | self.diffShowIntergroupColors.setChecked(qconfig.get_option("diff_show_intergroup_colors") in ("True", "1")) |
3752 | defaultDiff = qconfig.get_option("default_diff") |
3753 | @@ -404,31 +399,32 @@ |
3754 | item.setCheckState(0, QtCore.Qt.Checked) |
3755 | else: |
3756 | item.setCheckState(0, QtCore.Qt.Unchecked) |
3757 | - |
3758 | + |
3759 | item.setText(0, name) |
3760 | item.setText(1, command) |
3761 | return item |
3762 | - |
3763 | + |
3764 | builtin = create_ext_diff_item(gettext("Builtin Diff"),"") |
3765 | builtin.setFlags(QtCore.Qt.ItemIsSelectable | |
3766 | QtCore.Qt.ItemIsEnabled | |
3767 | - QtCore.Qt.ItemIsUserCheckable) |
3768 | - |
3769 | + QtCore.Qt.ItemIsUserCheckable) |
3770 | + |
3771 | extDiffs = qconfig.get_section('EXTDIFF') |
3772 | - for name, command in extDiffs.items(): |
3773 | + for name, command in list(extDiffs.items()): |
3774 | create_ext_diff_item(name, command) |
3775 | self.extDiffListIgnore = False |
3776 | |
3777 | # Merge |
3778 | if mergetools is not None: |
3779 | user_merge_tools = config.get_merge_tools() |
3780 | + # RJLRJL: check this - might need to be 'brz.default_mergetool' |
3781 | default_merge_tool = config.get_user_option('bzr.default_mergetool') |
3782 | if len(user_merge_tools) == 0: |
3783 | self.import_external_merge(user_merge_tools, config, qconfig) |
3784 | self.merge_tools_model.set_merge_tools(user_merge_tools, |
3785 | mergetools.known_merge_tools, default_merge_tool) |
3786 | self.merge_tools_model.sort(0, QtCore.Qt.AscendingOrder) |
3787 | - |
3788 | + |
3789 | def import_external_merge(self, user_merge_tools, config, qconfig): |
3790 | # don't ask to import if we already asked before |
3791 | if qconfig.get_option_as_bool('imported_external_merge'): |
3792 | @@ -453,7 +449,7 @@ |
3793 | user_merge_tools[name] = new_cmdline |
3794 | # set a flag to indicate that we've already asked about this |
3795 | qconfig.set_option('imported_external_merge', True) |
3796 | - |
3797 | + |
3798 | def convert_external_merge(self, external_merge): |
3799 | args = cmdline.split(external_merge) |
3800 | # %b %t %o -o %r |
3801 | @@ -483,9 +479,9 @@ |
3802 | pass |
3803 | |
3804 | # Name & e-mail |
3805 | - _name = unicode(self.nameEdit.text()).strip() |
3806 | - _email = unicode(self.emailEdit.text()).strip() |
3807 | - username = u'' |
3808 | + _name = str(self.nameEdit.text()).strip() |
3809 | + _email = str(self.emailEdit.text()).strip() |
3810 | + username = '' |
3811 | if _name: |
3812 | username = _name |
3813 | if _email: |
3814 | @@ -493,12 +489,12 @@ |
3815 | set_or_delete_option(parser, 'email', username) |
3816 | |
3817 | # Editor |
3818 | - editor = unicode(self.editorEdit.text()) |
3819 | + editor = str(self.editorEdit.text()) |
3820 | set_or_delete_option(parser, 'editor', editor) |
3821 | |
3822 | # E-mail client |
3823 | index = self.emailClientCombo.currentIndex() |
3824 | - mail_client = unicode(self.emailClientCombo.itemData(index).toString()) |
3825 | + mail_client = self.emailClientCombo.itemData(index) |
3826 | set_or_delete_option(parser, 'mail_client', mail_client) |
3827 | |
3828 | tabWidth = self.tabWidthSpinner.value() |
3829 | @@ -506,36 +502,36 @@ |
3830 | |
3831 | # Spellcheck language |
3832 | index = self.spellcheck_language_combo.currentIndex() |
3833 | - spellcheck_language = unicode(self.spellcheck_language_combo.itemData(index).toString()) |
3834 | + spellcheck_language = self.spellcheck_language_combo.itemData(index) |
3835 | set_or_delete_option(parser, 'spellcheck_language', spellcheck_language) |
3836 | |
3837 | # Branch source basedir |
3838 | - branchsource_basedir = unicode(self.branchsourceBasedirEdit.text()) |
3839 | + branchsource_basedir = str(self.branchsourceBasedirEdit.text()) |
3840 | qconfig.set_option('branchsource_basedir', branchsource_basedir) |
3841 | |
3842 | # Checkout basedir |
3843 | - checkout_basedir = unicode(self.checkoutBasedirEdit.text()) |
3844 | + checkout_basedir = str(self.checkoutBasedirEdit.text()) |
3845 | qconfig.set_option('checkout_basedir', checkout_basedir) |
3846 | |
3847 | # Aliases |
3848 | parser['ALIASES'] = {} |
3849 | for index in range(self.aliasesList.topLevelItemCount()): |
3850 | item = self.aliasesList.topLevelItem(index) |
3851 | - alias = unicode(item.text(0)) |
3852 | - command = unicode(item.text(1)) |
3853 | + alias = str(item.text(0)) |
3854 | + command = str(item.text(1)) |
3855 | if alias and command: |
3856 | parser['ALIASES'][alias] = command |
3857 | |
3858 | # Bug trackers |
3859 | - for name, value in parser.get('DEFAULT', {}).items(): |
3860 | + for name, value in list(parser.get('DEFAULT', {}).items()): |
3861 | m = _bug_tracker_re.match(name) |
3862 | if m: |
3863 | abbrev = m.group(1) |
3864 | del parser['DEFAULT']['bugtracker_%s_url' % abbrev] |
3865 | for index in range(self.bugTrackersList.topLevelItemCount()): |
3866 | item = self.bugTrackersList.topLevelItem(index) |
3867 | - abbrev = unicode(item.text(0)) |
3868 | - url = unicode(item.text(1)) |
3869 | + abbrev = str(item.text(0)) |
3870 | + url = str(item.text(1)) |
3871 | # FIXME add URL validation (must contain {id}) |
3872 | if abbrev and url: |
3873 | parser['DEFAULT']['bugtracker_%s_url' % abbrev] = url |
3874 | @@ -543,13 +539,13 @@ |
3875 | # Diff |
3876 | qconfig.set_option('diff_show_intergroup_colors', |
3877 | self.diffShowIntergroupColors.isChecked()) |
3878 | - |
3879 | + |
3880 | defaultDiff = None |
3881 | ext_diffs = {} |
3882 | for index in range(1, self.extDiffList.topLevelItemCount()): |
3883 | item = self.extDiffList.topLevelItem(index) |
3884 | - name = unicode(item.text(0)) |
3885 | - command = unicode(item.text(1)) |
3886 | + name = str(item.text(0)) |
3887 | + command = str(item.text(1)) |
3888 | if item.checkState(0) == QtCore.Qt.Checked: |
3889 | defaultDiff = command |
3890 | if name and command: |
3891 | @@ -557,8 +553,8 @@ |
3892 | qconfig.set_section('EXTDIFF', ext_diffs) |
3893 | qconfig.set_option('default_diff', |
3894 | defaultDiff) |
3895 | - |
3896 | - |
3897 | + |
3898 | + |
3899 | if hasattr(config, 'file_name'): |
3900 | file_name = config.file_name |
3901 | else: |
3902 | @@ -567,7 +563,7 @@ |
3903 | f = open(file_name, 'wb') |
3904 | parser.write(f) |
3905 | f.close() |
3906 | - |
3907 | + |
3908 | qconfig.save() |
3909 | |
3910 | # Merge |
3911 | @@ -577,7 +573,7 @@ |
3912 | if config.get_user_option(option, expand=False) is not None: |
3913 | config.remove_user_option(option) |
3914 | user_merge_tools = self.merge_tools_model.get_user_merge_tools() |
3915 | - for name, cmdline in user_merge_tools.iteritems(): |
3916 | + for name, cmdline in user_merge_tools.items(): |
3917 | orig_cmdline = config.find_merge_tool(name) |
3918 | if orig_cmdline is None or orig_cmdline != cmdline: |
3919 | config.set_user_option('bzr.mergetool.%s' % name, cmdline) |
3920 | @@ -600,8 +596,8 @@ |
3921 | """Check the inputs and return False if there is something wrong |
3922 | and save should be prohibited.""" |
3923 | # check whoami |
3924 | - _name = unicode(self.nameEdit.text()).strip() |
3925 | - _email = unicode(self.emailEdit.text()).strip() |
3926 | + _name = str(self.nameEdit.text()).strip() |
3927 | + _email = str(self.emailEdit.text()).strip() |
3928 | if (_name, _email) == ('', ''): |
3929 | if QtGui.QMessageBox.warning(self, "Configuration", |
3930 | "Name and E-mail settings should not be empty", |
3931 | @@ -656,7 +652,7 @@ |
3932 | index = self.extDiffList.indexOfTopLevelItem(item) |
3933 | if index >= 1: # You can't remove the builtin diff |
3934 | self.extDiffList.takeTopLevelItem(index) |
3935 | - |
3936 | + |
3937 | def extDiffListItemChanged(self, changed_item, col): |
3938 | if col == 0 and not self.extDiffListIgnore: |
3939 | checked_count = 0 |
3940 | @@ -664,7 +660,7 @@ |
3941 | item = self.extDiffList.topLevelItem(index) |
3942 | if item.checkState(0) == QtCore.Qt.Checked: |
3943 | checked_count += 1 |
3944 | - |
3945 | + |
3946 | if checked_count == 0: |
3947 | self.extDiffListIgnore = True |
3948 | changed_item.setCheckState(0, QtCore.Qt.Checked) |
3949 | @@ -677,24 +673,24 @@ |
3950 | item.setCheckState(0, QtCore.Qt.Unchecked) |
3951 | changed_item.setCheckState(0, QtCore.Qt.Checked) |
3952 | self.extDiffListIgnore = False |
3953 | - |
3954 | + |
3955 | def get_selected_merge_tool(self): |
3956 | sel_model = self.merge_ui.tools.selectionModel() |
3957 | if len(sel_model.selectedRows()) == 0: |
3958 | return None |
3959 | row = sel_model.selectedRows()[0].row() |
3960 | return self.merge_tools_model.get_merge_tool_name(row) |
3961 | - |
3962 | + |
3963 | def update_buttons(self): |
3964 | selected = self.get_selected_merge_tool() |
3965 | self.merge_ui.remove.setEnabled(selected is not None and |
3966 | self.merge_tools_model.is_user_merge_tool(selected)) |
3967 | self.merge_ui.set_default.setEnabled(selected is not None and |
3968 | self.merge_tools_model.get_default() != selected) |
3969 | - |
3970 | + |
3971 | def merge_tools_data_changed(self, top_left, bottom_right): |
3972 | self.update_buttons() |
3973 | - |
3974 | + |
3975 | def merge_tools_selectionChanged(self, selected, deselected): |
3976 | self.update_buttons() |
3977 | |
3978 | @@ -703,31 +699,31 @@ |
3979 | sel_model = self.merge_ui.tools.selectionModel() |
3980 | sel_model.select(index, QtGui.QItemSelectionModel.ClearAndSelect) |
3981 | self.merge_ui.tools.edit(index) |
3982 | - |
3983 | + |
3984 | def merge_tools_remove_clicked(self): |
3985 | sel_model = self.merge_ui.tools.selectionModel() |
3986 | assert len(sel_model.selectedRows()) > 0 |
3987 | for index in sel_model.selectedRows(): |
3988 | self.merge_tools_model.remove_merge_tool(index.row()) |
3989 | - |
3990 | + |
3991 | def merge_tools_set_default_clicked(self): |
3992 | sel_model = self.merge_ui.tools.selectionModel() |
3993 | self.merge_tools_model.set_default(self.get_selected_merge_tool()) |
3994 | - |
3995 | + |
3996 | def browseEditor(self): |
3997 | filename = QtGui.QFileDialog.getOpenFileName(self, |
3998 | gettext('Select editor executable'), |
3999 | '/') |
4000 | if filename: |
4001 | self.editorEdit.setText(filename) |
4002 | - |
4003 | + |
4004 | def browseCheckoutBasedir(self): |
4005 | filename = QtGui.QFileDialog.getExistingDirectory(self, |
4006 | gettext('Select base directory for checkouts'), |
4007 | '/') |
4008 | if filename: |
4009 | self.checkoutBasedirEdit.setText(filename) |
4010 | - |
4011 | + |
4012 | def browseBranchsourceBasedir(self): |
4013 | filename = QtGui.QFileDialog.getExistingDirectory(self, |
4014 | gettext('Select default directory for branch sources'), |
4015 | @@ -747,10 +743,10 @@ |
4016 | be very slow on machines where DNS is broken. So now we simply |
4017 | use the hostname. |
4018 | """ |
4019 | - |
4020 | + |
4021 | # This use to live in breezy.config._auto_user_id, but got removed, so |
4022 | # we have a copy. |
4023 | - |
4024 | + |
4025 | import sys |
4026 | if sys.platform == 'win32': |
4027 | from breezy import win32utils |
4028 | @@ -758,7 +754,7 @@ |
4029 | if name is None: |
4030 | raise errors.BzrError("Cannot autodetect user name.\n" |
4031 | "Please, set your name with command like:\n" |
4032 | - 'bzr whoami "Your Name <name@domain.com>"') |
4033 | + 'brz whoami "Your Name <name@domain.com>"') |
4034 | host = win32utils.get_host_name_unicode() |
4035 | if host is None: |
4036 | host = socket.gethostname() |
4037 | @@ -770,8 +766,7 @@ |
4038 | try: |
4039 | w = pwd.getpwuid(uid) |
4040 | except KeyError: |
4041 | - raise errors.BzrCommandError('Unable to determine your name. ' |
4042 | - 'Please use "bzr whoami" to set it.') |
4043 | + raise errors.BzrCommandError('Unable to determine your name. Please use "brz whoami" to set it.') |
4044 | |
4045 | # we try utf-8 first, because on many variants (like Linux), |
4046 | # /etc/passwd "should" be in utf-8, and because it's unlikely to give |
4047 | @@ -785,13 +780,11 @@ |
4048 | encoding = osutils.get_user_encoding() |
4049 | gecos = w.pw_gecos.decode(encoding) |
4050 | except UnicodeError: |
4051 | - raise errors.BzrCommandError('Unable to determine your name. ' |
4052 | - 'Use "bzr whoami" to set it.') |
4053 | + raise errors.BzrCommandError('Unable to determine your name. Use brz whoami" to set it.') |
4054 | try: |
4055 | username = w.pw_name.decode(encoding) |
4056 | except UnicodeError: |
4057 | - raise errors.BzrCommandError('Unable to determine your name. ' |
4058 | - 'Use "bzr whoami" to set it.') |
4059 | + raise errors.BzrCommandError('Unable to determine your name. Use "brz whoami" to set it.') |
4060 | |
4061 | comma = gecos.find(',') |
4062 | if comma == -1: |
4063 | @@ -807,8 +800,7 @@ |
4064 | user_encoding = osutils.get_user_encoding() |
4065 | realname = username = getpass.getuser().decode(user_encoding) |
4066 | except UnicodeDecodeError: |
4067 | - raise errors.BzrError("Can't decode username as %s." % \ |
4068 | - user_encoding) |
4069 | + raise errors.BzrError("Can't decode username as %s." % user_encoding) |
4070 | |
4071 | import socket |
4072 | return realname, (username + '@' + socket.gethostname()) |
4073 | @@ -818,7 +810,7 @@ |
4074 | COL_NAME = 0 |
4075 | COL_COMMANDLINE = 1 |
4076 | COL_COUNT = 2 |
4077 | - |
4078 | + |
4079 | def __init__(self): |
4080 | super(MergeToolsTableModel, self).__init__() |
4081 | self._order = [] |
4082 | @@ -826,21 +818,21 @@ |
4083 | self._known = {} |
4084 | self._default = None |
4085 | self._removed = [] |
4086 | - |
4087 | + |
4088 | def get_user_merge_tools(self): |
4089 | return self._user |
4090 | - |
4091 | + |
4092 | def set_merge_tools(self, user, known, default): |
4093 | self.beginResetModel() |
4094 | self._user = user |
4095 | self._known = known |
4096 | - self._order = user.keys() + known.keys() |
4097 | + self._order = list(user.keys()) + list(known.keys()) |
4098 | self._default = default |
4099 | self.endResetModel() |
4100 | |
4101 | def get_default(self): |
4102 | return self._default |
4103 | - |
4104 | + |
4105 | def set_default(self, new_default): |
4106 | old_row = None |
4107 | if self._default is not None: |
4108 | @@ -859,20 +851,20 @@ |
4109 | self.emit(QtCore.SIGNAL("dataChanged(QModelIndex,QModelIndex)"), |
4110 | self.index(new_row, self.COL_NAME), |
4111 | self.index(new_row, self.COL_NAME)) |
4112 | - |
4113 | + |
4114 | def get_removed_merge_tools(self): |
4115 | return self._removed |
4116 | - |
4117 | + |
4118 | def get_merge_tool_name(self, row): |
4119 | return self._order[row] |
4120 | - |
4121 | + |
4122 | def get_merge_tool_command_line(self, row): |
4123 | name = self._order[row] |
4124 | return self._user.get(name, self._known.get(name, None)) |
4125 | - |
4126 | + |
4127 | def is_user_merge_tool(self, name): |
4128 | return name in self._user |
4129 | - |
4130 | + |
4131 | def new_merge_tool(self): |
4132 | index = self.createIndex(len(self._order), 0) |
4133 | self.beginInsertRows(QtCore.QModelIndex(), index.row(), index.row()) |
4134 | @@ -880,7 +872,7 @@ |
4135 | self._user[''] = '' |
4136 | self.endInsertRows() |
4137 | return index |
4138 | - |
4139 | + |
4140 | def remove_merge_tool(self, row): |
4141 | name = self._order[row] |
4142 | if name not in self._user: |
4143 | @@ -892,26 +884,26 @@ |
4144 | del self._order[row] |
4145 | del self._user[name] |
4146 | self.endRemoveRows() |
4147 | - |
4148 | + |
4149 | def rowCount(self, parent): |
4150 | return len(self._order) |
4151 | - |
4152 | + |
4153 | def columnCount(self, parent): |
4154 | return self.COL_COUNT |
4155 | - |
4156 | + |
4157 | def data(self, index, role): |
4158 | name = self._order[index.row()] |
4159 | cmdline = self.get_merge_tool_command_line(index.row()) |
4160 | if role == QtCore.Qt.DisplayRole: |
4161 | if index.column() == self.COL_NAME: |
4162 | - return QtCore.QVariant(name) |
4163 | + return name |
4164 | elif index.column() == self.COL_COMMANDLINE: |
4165 | - return QtCore.QVariant(cmdline) |
4166 | + return cmdline |
4167 | elif role == QtCore.Qt.EditRole: |
4168 | if index.column() == self.COL_NAME: |
4169 | - return QtCore.QVariant(name) |
4170 | + return name |
4171 | elif index.column() == self.COL_COMMANDLINE: |
4172 | - return QtCore.QVariant(cmdline) |
4173 | + return cmdline |
4174 | elif role == QtCore.Qt.CheckStateRole: |
4175 | if index.column() == self.COL_NAME: |
4176 | return self._default == name and QtCore.Qt.Checked or QtCore.Qt.Unchecked |
4177 | @@ -919,8 +911,8 @@ |
4178 | if name in self._known: |
4179 | palette = QtGui.QApplication.palette() |
4180 | return palette.alternateBase() |
4181 | - return QtCore.QVariant() |
4182 | - |
4183 | + return None |
4184 | + |
4185 | def setData(self, index, value, role): |
4186 | name = self._order[index.row()] |
4187 | if role == QtCore.Qt.EditRole: |
4188 | @@ -932,7 +924,7 @@ |
4189 | self._removed.append(name) |
4190 | del self._order[index.row()] |
4191 | del self._user[name] |
4192 | - new_name = unicode(value.toString()) |
4193 | + new_name = str(value) |
4194 | self._order.insert(index.row(), new_name) |
4195 | self._user[new_name] = cmdline |
4196 | if self._default == name: |
4197 | @@ -942,57 +934,60 @@ |
4198 | self.sort(self.COL_NAME, QtCore.Qt.AscendingOrder) |
4199 | return True |
4200 | elif index.column() == self.COL_COMMANDLINE: |
4201 | - self._user[name] = unicode(value.toString()) |
4202 | + self._user[name] = str(value) |
4203 | self.emit(QtCore.SIGNAL("dataChanged(QModelIndex,QModelIndex)"), |
4204 | index, index) |
4205 | return True |
4206 | elif role == QtCore.Qt.CheckStateRole: |
4207 | if index.column() == self.COL_NAME: |
4208 | - if value.toInt() == (QtCore.Qt.Checked, True): |
4209 | + if int(value) == (QtCore.Qt.Checked, True): |
4210 | self.set_default(name) |
4211 | - elif (value.toInt() == (QtCore.Qt.Unchecked, True) and |
4212 | - self._default == name): |
4213 | + elif (int(value) == (QtCore.Qt.Unchecked, True) and self._default == name): |
4214 | self.set_default(None) |
4215 | + |
4216 | + # if value.toInt() == (QtCore.Qt.Checked, True): |
4217 | + # self.set_default(name) |
4218 | + # elif (value.toInt() == (QtCore.Qt.Unchecked, True) and self._default == name): |
4219 | + # self.set_default(None) |
4220 | return False |
4221 | - |
4222 | + |
4223 | def flags(self, index): |
4224 | - f = super(MergeToolsTableModel, self).flags(index) |
4225 | + f = super().flags(index) |
4226 | name = self._order[index.row()] |
4227 | if name not in self._known: |
4228 | f = f | QtCore.Qt.ItemIsEditable |
4229 | if index.column() == self.COL_NAME: |
4230 | f = f | QtCore.Qt.ItemIsUserCheckable |
4231 | return f |
4232 | - |
4233 | + |
4234 | def headerData(self, section, orientation, role): |
4235 | if orientation == QtCore.Qt.Horizontal: |
4236 | if section == self.COL_NAME: |
4237 | if role == QtCore.Qt.DisplayRole: |
4238 | - return QtCore.QVariant(gettext("Name")) |
4239 | + return gettext("Name") |
4240 | elif section == self.COL_COMMANDLINE: |
4241 | if role == QtCore.Qt.DisplayRole: |
4242 | - return QtCore.QVariant(gettext("Command Line")) |
4243 | - return QtCore.QVariant() |
4244 | + return gettext("Command Line") |
4245 | + return None |
4246 | |
4247 | def sort(self, column, sortOrder): |
4248 | self.emit(QtCore.SIGNAL("layoutAboutToBeChanged()")) |
4249 | - index_map = self._order[:] # copy |
4250 | + index_map = self._order[:] # copy |
4251 | + |
4252 | def tool_cmp(a, b): |
4253 | if column == self.COL_NAME: |
4254 | return cmp(a, b) |
4255 | elif column == self.COL_COMMANDLINE: |
4256 | - return cmp(self.get_merge_tool_command_line(a), |
4257 | - self.get_merge_tool_command_line(b)) |
4258 | + return cmp(self.get_merge_tool_command_line(a), self.get_merge_tool_command_line(b)) |
4259 | return 0 |
4260 | - self._order.sort(cmp=tool_cmp, |
4261 | - reverse=sortOrder==QtCore.Qt.DescendingOrder) |
4262 | + |
4263 | + # self._order.sort(cmp=tool_cmp, reverse=sortOrder==QtCore.Qt.DescendingOrder) |
4264 | for i in range(0, len(index_map)): |
4265 | index_map[i] = self._order.index(index_map[i]) |
4266 | from_list = [] |
4267 | to_list = [] |
4268 | for col in range(0, self.columnCount(None)): |
4269 | from_list.extend([self.index(i, col) for i in index_map]) |
4270 | - to_list.extend([self.index(i, col) |
4271 | - for i in range(0, len(index_map))]) |
4272 | + to_list.extend([self.index(i, col) for i in range(0, len(index_map))]) |
4273 | self.changePersistentIndexList(from_list, to_list) |
4274 | self.emit(QtCore.SIGNAL("layoutChanged()")) |
4275 | |
4276 | === modified file 'lib/conflicts.py' |
4277 | --- lib/conflicts.py 2017-09-11 06:53:22 +0000 |
4278 | +++ lib/conflicts.py 2020-07-16 14:28:25 +0000 |
4279 | @@ -88,9 +88,9 @@ |
4280 | self.connect(self.merge_tools_combo, |
4281 | QtCore.SIGNAL("currentIndexChanged(int)"), |
4282 | self.update_merge_tool_ui) |
4283 | - |
4284 | + |
4285 | self.merge_tool_error = QtGui.QLabel('', self) |
4286 | - |
4287 | + |
4288 | self.program_launch_button = QtGui.QPushButton(gettext("&Launch..."), self) |
4289 | self.program_launch_button.setEnabled(False) |
4290 | self.connect( |
4291 | @@ -121,15 +121,15 @@ |
4292 | hbox.addWidget(autobutton) |
4293 | hbox.addWidget(buttonbox) |
4294 | vbox.addLayout(hbox) |
4295 | - self.initialize_ui() |
4296 | + self.initialize_ui() |
4297 | |
4298 | def initialize_ui(self): |
4299 | config = GlobalConfig() |
4300 | if mergetools is not None: |
4301 | # get user-defined merge tools |
4302 | - defined_tools = config.get_merge_tools().keys() |
4303 | + defined_tools = list(config.get_merge_tools().keys()) |
4304 | # get predefined merge tools |
4305 | - defined_tools += mergetools.known_merge_tools.keys() |
4306 | + defined_tools += list(mergetools.known_merge_tools.keys()) |
4307 | # sort them nicely |
4308 | defined_tools.sort() |
4309 | for merge_tool in defined_tools: |
4310 | @@ -174,8 +174,8 @@ |
4311 | item = QtGui.QTreeWidgetItem() |
4312 | item.setText(0, conflict.path) |
4313 | item.setText(1, gettext(conflict.typestring)) |
4314 | - item.setData(0, QtCore.Qt.UserRole, QtCore.QVariant(conflict.file_id or '')) # file_id is None for non-versioned items, so we force it to be empty string to avoid Qt error |
4315 | - item.setData(1, QtCore.Qt.UserRole, QtCore.QVariant(conflict.typestring)) |
4316 | + item.setData(0, QtCore.Qt.UserRole, conflict.file_id or '') # file_id is None for non-versioned items, so we force it to be empty string to avoid Qt error |
4317 | + item.setData(1, QtCore.Qt.UserRole, conflict.typestring) |
4318 | items.append(item) |
4319 | |
4320 | if len(items) == 0 and self.conflicts_list.topLevelItemCount() > 0: |
4321 | @@ -213,8 +213,8 @@ |
4322 | if not enabled: |
4323 | return |
4324 | config = GlobalConfig() |
4325 | - cmdline = config.find_merge_tool(unicode(self.merge_tools_combo.currentText())) |
4326 | - file_id = str(items[0].data(0, QtCore.Qt.UserRole).toString()) |
4327 | + cmdline = config.find_merge_tool(str(self.merge_tools_combo.currentText())) |
4328 | + file_id = items[0].data(0, QtCore.Qt.UserRole) |
4329 | if not file_id: |
4330 | # bug https://bugs.launchpad.net/qbrz/+bug/655451 |
4331 | return |
4332 | @@ -251,9 +251,9 @@ |
4333 | # XXX why we need to use file_id -> path conversion if we already have filename??? |
4334 | # this conversion fails in the case when user removed file or directory |
4335 | # which marked as conflicted (e.g. in missing parent conflict case). |
4336 | - #~file_id = str(item.data(0, QtCore.Qt.UserRole).toString()) |
4337 | - #~file_names.append(self.wt.id2path(file_id)) |
4338 | - file_names.append(unicode(item.text(0))) |
4339 | + # ~file_id = str(item.data(0, QtCore.Qt.UserRole).toString()) |
4340 | + # ~file_names.append(self.wt.id2path(file_id)) |
4341 | + file_names.append(str(item.text(0))) |
4342 | resolve(self.wt, file_names, action=action) |
4343 | self.refresh() |
4344 | |
4345 | @@ -266,10 +266,10 @@ |
4346 | items = self.conflicts_list.selectedItems() |
4347 | error_msg = "" |
4348 | enabled = True |
4349 | - if len(items) != 1 or items[0].data(1, QtCore.Qt.UserRole).toString() != "text conflict": |
4350 | + if len(items) != 1 or items[0].data(1, QtCore.Qt.UserRole) != "text conflict": |
4351 | enabled = False |
4352 | config = GlobalConfig() |
4353 | - tool = unicode(self.merge_tools_combo.currentText()) |
4354 | + tool = str(self.merge_tools_combo.currentText()) |
4355 | cmdline = config.find_merge_tool(tool) |
4356 | if cmdline is None: |
4357 | error_msg = gettext("Set up external_merge app in qconfig under the Merge tab") |
4358 | |
4359 | === modified file 'lib/decorators.py' |
4360 | --- lib/decorators.py 2017-09-11 06:53:22 +0000 |
4361 | +++ lib/decorators.py 2020-07-16 14:28:25 +0000 |
4362 | @@ -29,12 +29,12 @@ |
4363 | def _run(*args, **kwargs): |
4364 | from breezy.trace import mutter |
4365 | a = ','.join(repr(i) for i in args) |
4366 | - b = ','.join('%s=%r' % (i,j) for (i,j) in kwargs.iteritems()) |
4367 | + b = ','.join('%s=%r' % (i,j) for (i,j) in kwargs.items()) |
4368 | if a and b: |
4369 | a = a + ',' + b |
4370 | else: |
4371 | a = a or b |
4372 | - func_name = unbound.func_name |
4373 | + func_name = unbound.__name__ |
4374 | mutter('Called %s(%s)' % (func_name, a)) |
4375 | result = unbound(*args, **kwargs) |
4376 | mutter('%s returned %r' % (func_name, result)) |
4377 | |
4378 | === modified file 'lib/diff.py' |
4379 | --- lib/diff.py 2018-01-31 22:46:16 +0000 |
4380 | +++ lib/diff.py 2020-07-16 14:28:25 +0000 |
4381 | @@ -24,9 +24,9 @@ |
4382 | from breezy.plugins.qbrz.lib.diff_arg import * # import DiffArgProvider classes |
4383 | from breezy.plugins.qbrz.lib.i18n import gettext |
4384 | from breezy.plugins.qbrz.lib.subprocess import SimpleSubProcessDialog |
4385 | -from breezy.plugins.qbrz.lib.util import ( |
4386 | +from breezy.plugins.qbrz.lib.util import ( |
4387 | get_qbrz_config, |
4388 | - is_binary_content, |
4389 | + content_seems_to_be_binary, |
4390 | ) |
4391 | |
4392 | from breezy.lazy_import import lazy_import |
4393 | @@ -37,7 +37,7 @@ |
4394 | import sys |
4395 | import os |
4396 | import glob |
4397 | -from breezy.patiencediff import PatienceSequenceMatcher as SequenceMatcher |
4398 | +from patiencediff import PatienceSequenceMatcher as SequenceMatcher |
4399 | from breezy.plugins.qbrz.lib.i18n import gettext, ngettext, N_ |
4400 | from breezy import trace, osutils, cmdline |
4401 | from breezy.workingtree import WorkingTree |
4402 | @@ -51,21 +51,21 @@ |
4403 | if default_diff is None: |
4404 | default_diff = "" |
4405 | ext_diffs = {gettext("Builtin Diff"):""} |
4406 | -for name, command in qconfig.get_section('EXTDIFF').items(): |
4407 | +for name, command in list(qconfig.get_section('EXTDIFF').items()): |
4408 | ext_diffs[name] = command |
4409 | |
4410 | |
4411 | def show_diff(arg_provider, ext_diff=None, parent_window=None, context=None): |
4412 | - |
4413 | + |
4414 | if ext_diff is None: |
4415 | ext_diff = default_diff |
4416 | - |
4417 | + |
4418 | if ext_diff == "": |
4419 | - |
4420 | + |
4421 | # We can't import this globaly becuse it ties to import us, |
4422 | # which causes and Import Error. |
4423 | from breezy.plugins.qbrz.lib.diffwindow import DiffWindow |
4424 | - |
4425 | + |
4426 | window = DiffWindow(arg_provider, parent=parent_window) |
4427 | window.show() |
4428 | if parent_window: |
4429 | @@ -112,24 +112,24 @@ |
4430 | |
4431 | |
4432 | class ExtDiffMenu(QtGui.QMenu): |
4433 | - |
4434 | + |
4435 | def __init__ (self, parent=None, include_builtin=True, set_default=True): |
4436 | QtGui.QMenu.__init__(self, gettext("Show &differences"), parent) |
4437 | - |
4438 | - for name, command in ext_diffs.items(): |
4439 | + |
4440 | + for name, command in list(ext_diffs.items()): |
4441 | if command == "" and include_builtin or not command == "": |
4442 | action = QtGui.QAction(name, self) |
4443 | - action.setData(QtCore.QVariant (command)) |
4444 | + action.setData(command) |
4445 | if command == default_diff and set_default: |
4446 | self.setDefaultAction(action) |
4447 | self.addAction(action) |
4448 | - |
4449 | + |
4450 | self.connect(self, QtCore.SIGNAL("triggered(QAction *)"), |
4451 | self.triggered) |
4452 | - |
4453 | + |
4454 | def triggered(self, action): |
4455 | - ext_diff = unicode(action.data().toString()) |
4456 | - self.emit(QtCore.SIGNAL("triggered(QString)"), QtCore.QString(ext_diff)) |
4457 | + ext_diff = str(action.data()) |
4458 | + self.emit(QtCore.SIGNAL("triggered(QString)"), ext_diff) |
4459 | |
4460 | |
4461 | class DiffButtons(QtGui.QWidget): |
4462 | @@ -164,7 +164,7 @@ |
4463 | |
4464 | def triggered(self, ext_diff=None): |
4465 | if ext_diff is None: |
4466 | - ext_diff = QtCore.QString(default_diff) |
4467 | + ext_diff = default_diff |
4468 | self.emit(QtCore.SIGNAL("triggered(QString)"), ext_diff) |
4469 | |
4470 | |
4471 | @@ -180,21 +180,20 @@ |
4472 | |
4473 | @classmethod |
4474 | def iter_items(cls, trees, specific_files=None, filter=None, lock_trees=False): |
4475 | + """ |
4476 | + RJLRJL: updated to call .iter_changes directly |
4477 | + """ |
4478 | try: |
4479 | cleanup = [] |
4480 | if lock_trees: |
4481 | for t in trees: |
4482 | cleanup.append(t.lock_read().unlock) |
4483 | |
4484 | - changes = trees[1].iter_changes(trees[0], |
4485 | - specific_files=specific_files, |
4486 | - require_versioned=True) |
4487 | - |
4488 | - def changes_key(change): |
4489 | - return change[1][1] or change[1][0] |
4490 | - |
4491 | - for (file_id, paths, changed_content, versioned, parent, name, kind, |
4492 | - executable) in sorted(changes, key=changes_key): |
4493 | + # changes = trees[1].iter_changes(trees[0], specific_files=specific_files, require_versioned=True) |
4494 | + |
4495 | + # def changes_key(change): |
4496 | + # return change[1][1] or change[1][0] |
4497 | + for change in trees[1].iter_changes(trees[0], specific_files=specific_files, require_versioned=True): |
4498 | # file_id -> ascii string |
4499 | # paths -> 2-tuple (old, new) fullpaths unicode/None |
4500 | # changed_content -> bool |
4501 | @@ -205,8 +204,8 @@ |
4502 | # executable -> 2-tuple (bool/None, bool/None) |
4503 | # NOTE: None value used for non-existing entry in corresponding |
4504 | # tree, e.g. for added/deleted file |
4505 | - di = DiffItem.create(trees, file_id, paths, changed_content, |
4506 | - versioned, parent, name, kind, executable, |
4507 | + di = DiffItem.create(trees, change.file_id, change.path, change.changed_content, |
4508 | + change.versioned, change.parent_id, change.name, change.kind, change.executable, |
4509 | filter = filter) |
4510 | if not di: |
4511 | continue |
4512 | @@ -216,7 +215,7 @@ |
4513 | cleanup.pop()() |
4514 | |
4515 | @classmethod |
4516 | - def create(cls, trees, file_id, paths, changed_content, versioned, |
4517 | + def create(cls, trees, file_id, paths, changed_content, versioned, |
4518 | parent, name, kind, executable, filter = None): |
4519 | |
4520 | if parent == (None, None): # filter out TREE_ROOT (?) |
4521 | @@ -237,8 +236,8 @@ |
4522 | for ix in range(2): |
4523 | if versioned[ix]: |
4524 | try: |
4525 | - dates[ix] = trees[ix].get_file_mtime(paths[ix], file_id) |
4526 | - except OSError, e: |
4527 | + dates[ix] = trees[ix].get_file_mtime(paths[ix]) |
4528 | + except OSError as e: |
4529 | if not renamed or e.errno != errno.ENOENT: |
4530 | raise |
4531 | # If we get ENOENT error then probably we trigger |
4532 | @@ -248,7 +247,7 @@ |
4533 | # ghosts around us (see Bug #513096) |
4534 | dates[ix] = 0 # using 1970/1/1 instead |
4535 | |
4536 | - properties_changed = [] |
4537 | + properties_changed = [] |
4538 | if bool(executable[0]) != bool(executable[1]): |
4539 | descr = {True: "+x", False: "-x", None: None} |
4540 | properties_changed.append((descr[executable[0]], |
4541 | @@ -268,7 +267,7 @@ |
4542 | if filter and not filter(status): |
4543 | return None |
4544 | |
4545 | - return cls(trees, file_id, paths, changed_content, versioned, kind, |
4546 | + return cls(trees, file_id, paths, changed_content, versioned, kind, |
4547 | properties_changed, dates, status) |
4548 | |
4549 | def __init__(self, trees, file_id, paths, changed_content, versioned, kind, |
4550 | @@ -294,16 +293,17 @@ |
4551 | self._load_lines() |
4552 | |
4553 | def _load_lines(self): |
4554 | - if ((self.versioned[0] != self.versioned[1] or self.changed_content) |
4555 | - and (self.kind[0] == 'file' or self.kind[1] == 'file')): |
4556 | + if ((self.versioned[0] != self.versioned[1] or self.changed_content) and (self.kind[0] == 'file' or self.kind[1] == 'file')): |
4557 | lines = [] |
4558 | binary = False |
4559 | + # print('\n_load_lines', self.file_id) |
4560 | for ix, tree in enumerate(self.trees): |
4561 | content = () |
4562 | if self.versioned[ix] and self.kind[ix] == 'file': |
4563 | content = tree.get_file_lines(tree.id2path(self.file_id)) |
4564 | + # print('\n\tcontent loaded for ', tree.id2path(self.file_id), self.file_id) |
4565 | lines.append(content) |
4566 | - binary = binary or is_binary_content(content) |
4567 | + binary = binary or content_seems_to_be_binary(content) |
4568 | self._lines = lines |
4569 | self._binary = binary |
4570 | else: |
4571 | @@ -344,11 +344,13 @@ |
4572 | return groups |
4573 | |
4574 | def difference_groups(self, lines, complete, ignore_whitespace): |
4575 | + # RJL Changed strings to bytes for pattern-matching and coerced |
4576 | + # left and right to lists (instead of generators) in 'if...' |
4577 | left, right = lines |
4578 | if ignore_whitespace: |
4579 | - re_whitespaces = re.compile("\s+") |
4580 | - left = (re_whitespaces.sub(" ", line) for line in left) |
4581 | - right = (re_whitespaces.sub(" ", line) for line in right) |
4582 | + re_whitespaces = re.compile(b"\s+") |
4583 | + left = list((re_whitespaces.sub(b" ", line) for line in left)) |
4584 | + right = list((re_whitespaces.sub(b" ", line) for line in right)) |
4585 | matcher = SequenceMatcher(None, left, right) |
4586 | if complete: |
4587 | groups = list([matcher.get_opcodes()]) |
4588 | @@ -358,9 +360,9 @@ |
4589 | return groups |
4590 | |
4591 | def get_unicode_lines(self, encodings): |
4592 | - """Return pair of unicode lines for each side of diff. |
4593 | - Parameter encodings is 2-list or 2-tuple with encoding names (str) |
4594 | - for each side of diff. |
4595 | + """ |
4596 | + Return pair of unicode lines for each side of diff. |
4597 | + Parameter encodings is 2-list or 2-tuple with encoding names (str) for each side of diff. |
4598 | """ |
4599 | lines = self.lines |
4600 | ulines = self._ulines |
4601 | @@ -372,7 +374,7 @@ |
4602 | else: |
4603 | try: |
4604 | ulines[i] = [l.decode(encodings[i]) for l in lines[i]] |
4605 | - except UnicodeDecodeError, e: |
4606 | + except UnicodeDecodeError as e: |
4607 | filename = self.paths[i] |
4608 | trace.note("Some characters in file %s " |
4609 | "could not be properly decoded " |
4610 | @@ -396,7 +398,7 @@ |
4611 | parent = osutils.joinpath([osutils.tempfile.gettempdir(), 'qbrz']) |
4612 | if not os.path.isdir(parent): |
4613 | os.mkdir(parent) |
4614 | - self._root = osutils.mkdtemp(prefix='qbrz/bzr-diff-') |
4615 | + self._root = osutils.mkdtemp(prefix='qbrz/brz-diff-') |
4616 | self.prefixes = {} |
4617 | self._set_prefix() |
4618 | |
4619 | @@ -414,9 +416,10 @@ |
4620 | self.new_prefix = self.get_prefix(self.new_tree) |
4621 | |
4622 | def get_prefix(self, tree): |
4623 | + |
4624 | def get_key(tree): |
4625 | if hasattr(tree, "get_revision_id"): |
4626 | - return tree.__class__.__name__ + ":" + tree.get_revision_id() |
4627 | + return tree.__class__.__name__ + ":" + tree.get_revision_id().decode('utf-8') |
4628 | elif hasattr(tree, "abspath"): |
4629 | return tree.__class__.__name__ + ":" + tree.abspath("") |
4630 | else: |
4631 | @@ -425,7 +428,7 @@ |
4632 | if tree is None: |
4633 | return None |
4634 | key = get_key(tree) |
4635 | - if self.prefixes.has_key(key): |
4636 | + if key in self.prefixes: |
4637 | return self.prefixes[key] |
4638 | prefix = str(len(self.prefixes) + 1) |
4639 | self.prefixes[key] = prefix |
4640 | @@ -466,31 +469,30 @@ |
4641 | if os.path.isdir(path): |
4642 | open(os.path.join(path, ".delete"), "w").close() |
4643 | |
4644 | - def _write_file(self, relpath, tree, prefix, force_temp=False, |
4645 | - allow_write=False, file_id=None): |
4646 | + def _write_file(self, relpath, tree, prefix, force_temp=False, allow_write=False, file_id=None): |
4647 | if force_temp or not isinstance(tree, WorkingTree): |
4648 | full_path = self._safe_filename(prefix, relpath) |
4649 | if os.path.isfile(full_path): |
4650 | return full_path |
4651 | - return DiffFromTool._write_file(self, relpath, tree, prefix, |
4652 | - force_temp, allow_write, file_id) |
4653 | + # return DiffFromTool._write_file(self, relpath, tree, prefix, force_temp, allow_write, file_id) |
4654 | + return DiffFromTool._write_file(self, relpath, tree, prefix, force_temp, allow_write) |
4655 | |
4656 | - def _prepare_files(self, old_path, new_path, force_temp=False, |
4657 | - file_id=None, allow_write_new=False): |
4658 | - old_disk_path = self._write_file(old_path, self.old_tree, |
4659 | - self.old_prefix, force_temp, |
4660 | - file_id=file_id) |
4661 | - new_disk_path = self._write_file(new_path, self.new_tree, |
4662 | - self.new_prefix, force_temp, |
4663 | - allow_write=allow_write_new, |
4664 | - file_id=file_id) |
4665 | - return old_disk_path, new_disk_path |
4666 | + # def _prepare_files(self, old_path, new_path, force_temp=False, |
4667 | + # file_id=None, allow_write_new=False): |
4668 | + # old_disk_path = self._write_file(old_path, self.old_tree, |
4669 | + # self.old_prefix, force_temp, |
4670 | + # file_id=file_id) |
4671 | + # new_disk_path = self._write_file(new_path, self.new_tree, |
4672 | + # self.new_prefix, force_temp, |
4673 | + # allow_write=allow_write_new, |
4674 | + # file_id=file_id) |
4675 | + # return old_disk_path, new_disk_path |
4676 | |
4677 | def _execute(self, old_path, new_path): |
4678 | command = self._get_command(old_path, new_path) |
4679 | try: |
4680 | subprocess.Popen(command, cwd=self._root) |
4681 | - except OSError, e: |
4682 | + except OSError as e: |
4683 | if e.errno == errno.ENOENT: |
4684 | raise ExecutableMissing(command[0]) |
4685 | else: |
4686 | @@ -500,12 +502,15 @@ |
4687 | def diff(self, file_id): |
4688 | try: |
4689 | new_path = self.new_tree.id2path(file_id) |
4690 | - new_kind = self.new_tree.kind(new_path, file_id) |
4691 | + # new_kind = self.new_tree.kind(new_path, file_id) |
4692 | + new_kind = self.new_tree.kind(new_path) |
4693 | old_path = self.old_tree.id2path(file_id) |
4694 | - old_kind = self.old_tree.kind(old_path, file_id) |
4695 | + # old_kind = self.old_tree.kind(old_path, file_id) |
4696 | + old_kind = self.old_tree.kind(old_path) |
4697 | except NoSuchId: |
4698 | return DiffPath.CANNOT_DIFF |
4699 | - return DiffFromTool.diff(self, file_id, old_path, new_path, old_kind, new_kind) |
4700 | + # return DiffFromTool.diff(self, file_id, old_path, new_path, old_kind, new_kind) |
4701 | + return DiffFromTool.diff(self, old_path, new_path, old_kind, new_kind) |
4702 | |
4703 | class ExtDiffContext(QtCore.QObject): |
4704 | """ |
4705 | @@ -516,7 +521,7 @@ |
4706 | """ |
4707 | :parent: parent widget. If specified, cache is deleted automatically |
4708 | when parent is closed. |
4709 | - :to_file: stream to write output messages. If not specified, |
4710 | + :to_file: stream to write output messages. If not specified, |
4711 | stdout is used. |
4712 | :path_encoding: encoding of path |
4713 | """ |
4714 | @@ -562,8 +567,7 @@ |
4715 | Set or change diff command and diffed trees. |
4716 | """ |
4717 | if self._differ is None: |
4718 | - self._differ = _ExtDiffer(command_string, old_tree, new_tree, |
4719 | - self.to_file, self.path_encoding) |
4720 | + self._differ = _ExtDiffer(command_string, old_tree, new_tree, self.to_file, self.path_encoding) |
4721 | else: |
4722 | self._differ.set_trees(old_tree, new_tree) |
4723 | self._differ.set_command_string(command_string) |
4724 | @@ -577,7 +581,7 @@ |
4725 | """ |
4726 | Show diffs of specified file_ids. |
4727 | NOTE: Directories cannot be specified. |
4728 | - Use diff_tree or diff_paths instead when specifing directory. |
4729 | + Use diff_tree or diff_paths instead when specifing directory. |
4730 | """ |
4731 | cleanup = [] |
4732 | try: |
4733 | |
4734 | === modified file 'lib/diffview.py' |
4735 | --- lib/diffview.py 2017-09-11 06:53:22 +0000 |
4736 | +++ lib/diffview.py 2020-07-16 14:28:25 +0000 |
4737 | @@ -21,7 +21,7 @@ |
4738 | |
4739 | import re |
4740 | from breezy import timestamp |
4741 | -from breezy.patiencediff import PatienceSequenceMatcher as SequenceMatcher |
4742 | +from patiencediff import PatienceSequenceMatcher as SequenceMatcher |
4743 | from breezy.plugins.qbrz.lib.i18n import gettext |
4744 | from breezy.plugins.qbrz.lib.util import ( |
4745 | file_extension, |
4746 | @@ -66,18 +66,18 @@ |
4747 | |
4748 | config = get_qbrz_config() |
4749 | component_dict = {0:'fill', 1:'bound'} |
4750 | -for key in colors.iterkeys(): |
4751 | +for key in colors.keys(): |
4752 | for comp in [0,1]: |
4753 | color = None |
4754 | try: |
4755 | color = config.get_color(key + '_' + component_dict[comp], |
4756 | 'QDIFF COLORS') |
4757 | - except ValueError, msg: |
4758 | + except ValueError as msg: |
4759 | #error handling. |
4760 | mutter(str(msg)) |
4761 | if None != color: |
4762 | colors[key][comp] = color |
4763 | - |
4764 | + |
4765 | |
4766 | #Get a user-defined replacement text background |
4767 | try: |
4768 | @@ -85,11 +85,11 @@ |
4769 | 'QDIFF COLORS') |
4770 | if None != new_interline_bg: |
4771 | interline_changes_background = new_interline_bg |
4772 | -except ValueError, msg: |
4773 | +except ValueError as msg: |
4774 | mutter(str(msg)) |
4775 | |
4776 | brushes = {} |
4777 | -for kind, cols in colors.items(): |
4778 | +for kind, cols in list(colors.items()): |
4779 | brushes[kind] = (QtGui.QBrush(cols[0]), QtGui.QBrush(cols[1])) |
4780 | |
4781 | |
4782 | @@ -126,7 +126,7 @@ |
4783 | if block_y > bot: |
4784 | break |
4785 | painter.drawLine(0, block_y, w, block_y) |
4786 | - |
4787 | + |
4788 | pen.setWidth(1) |
4789 | for y_top, y_bot, kind in self.changes: |
4790 | y_top -= y |
4791 | @@ -140,7 +140,7 @@ |
4792 | painter.drawLine(0, y_top, w, y_top) |
4793 | painter.drawLine(0, y_bot - 1, w, y_bot - 1) |
4794 | del painter |
4795 | - QtGui.QTextBrowser.paintEvent(self, event) |
4796 | + QtGui.QTextBrowser.paintEvent(self, event) |
4797 | |
4798 | def wheelEvent(self, event): |
4799 | if event.orientation() == QtCore.Qt.Vertical and self.scrollbar: |
4800 | @@ -155,7 +155,7 @@ |
4801 | self.scrollbar = None |
4802 | self.view = parent |
4803 | self.clear() |
4804 | - |
4805 | + |
4806 | def clear(self): |
4807 | self.changes = [] |
4808 | self.infoBlocks = [] |
4809 | @@ -203,7 +203,7 @@ |
4810 | ly_bot -= ly + 1 |
4811 | ry_top -= ry |
4812 | ry_bot -= ry + 1 |
4813 | - |
4814 | + |
4815 | if ly_top < 0 and ly_bot < 0 and ry_top < 0 and ry_bot < 0: |
4816 | continue |
4817 | if ly_top > h and ly_bot > h and ry_top > h and ry_bot > h: |
4818 | @@ -221,7 +221,7 @@ |
4819 | |
4820 | painter.fillPath(region, brushes[kind][0]) |
4821 | painter.setPen(colors[kind][1]) |
4822 | - for path, aa in zip((upper_line, lower_line), |
4823 | + for path, aa in zip((upper_line, lower_line), |
4824 | (ly_top != ry_top, ly_bot != ry_bot)): |
4825 | painter.setRenderHints(QtGui.QPainter.Antialiasing, aa) |
4826 | painter.drawPath(path) |
4827 | @@ -264,7 +264,7 @@ |
4828 | b.scrollbar = self |
4829 | |
4830 | for i, scbar in enumerate([self] + [b.verticalScrollBar() for b in browsers]): |
4831 | - self.connect(scbar, QtCore.SIGNAL("valueChanged(int)"), |
4832 | + self.connect(scbar, QtCore.SIGNAL("valueChanged(int)"), |
4833 | lambda value, target=i : self.scrolled(target)) |
4834 | |
4835 | self.connect(browsers[0], QtCore.SIGNAL("resized()"), self.adjust_range) |
4836 | @@ -398,19 +398,19 @@ |
4837 | titleFont = QtGui.QFont(self.font()) |
4838 | titleFont.setPointSize(titleFont.pointSize() * 140 / 100) |
4839 | titleFont.setBold(True) |
4840 | - |
4841 | + |
4842 | self.monospacedFont = get_monospace_font() |
4843 | metadataFont = QtGui.QFont(self.font()) |
4844 | metadataFont.setPointSize(titleFont.pointSize() * 70 / 100) |
4845 | metadataLabelFont = QtGui.QFont(metadataFont) |
4846 | metadataLabelFont.setBold(True) |
4847 | - |
4848 | + |
4849 | self.monospacedFormat = QtGui.QTextCharFormat() |
4850 | self.monospacedFormat.setFont(self.monospacedFont) |
4851 | self.ttype_formater = CachedTTypeFormater( |
4852 | QtGui.QTextCharFormat(self.monospacedFormat)) |
4853 | self.background = self.monospacedFormat.background() |
4854 | - |
4855 | + |
4856 | self.titleFormat = QtGui.QTextCharFormat() |
4857 | self.titleFormat.setFont(titleFont) |
4858 | self.metadataFormat = QtGui.QTextCharFormat() |
4859 | @@ -436,12 +436,12 @@ |
4860 | b.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) |
4861 | |
4862 | self.cursors = [QtGui.QTextCursor(doc) for doc in self.docs] |
4863 | - |
4864 | + |
4865 | for i, (panel, doc, cursor) in enumerate(zip(self.guidebar_panels, |
4866 | self.docs, self.cursors)): |
4867 | doc.setUndoRedoEnabled(False) |
4868 | doc.setDefaultFont(self.monospacedFont) |
4869 | - |
4870 | + |
4871 | panel.edit.setDocument(doc) |
4872 | self.addWidget(panel) |
4873 | self.setCollapsible(i, False) |
4874 | @@ -457,15 +457,15 @@ |
4875 | self.connect(self.browsers[1].horizontalScrollBar(), QtCore.SIGNAL("valueChanged(int)"), self.syncHorizontalSlider2) |
4876 | |
4877 | self.rewinded = False |
4878 | - |
4879 | + |
4880 | self.lastModifiedLabel = gettext('Last modified:') |
4881 | self.statusLabel = gettext('Status:') |
4882 | self.kindLabel = gettext('Kind:') |
4883 | self.propertiesLabel = gettext('Properties:') |
4884 | - |
4885 | + |
4886 | self.image_exts = ['.'+str(i) |
4887 | for i in QtGui.QImageReader.supportedImageFormats()] |
4888 | - |
4889 | + |
4890 | config = get_qbrz_config() |
4891 | self.show_intergroup_colors = config.get_option("diff_show_intergroup_colors") in ("True", "1") |
4892 | |
4893 | @@ -522,16 +522,16 @@ |
4894 | else: |
4895 | cursor.insertText(" ", self.metadataFormat) |
4896 | cursor.insertBlock() |
4897 | - |
4898 | + |
4899 | infoBlocks = (cursors[0].block().layout(), |
4900 | cursors[1].block().layout()) |
4901 | changes = [] |
4902 | - |
4903 | + |
4904 | if not binary: |
4905 | for cursor in cursors: |
4906 | cursor.setCharFormat(self.monospacedFormat) |
4907 | cursor.insertBlock() |
4908 | - |
4909 | + |
4910 | def fix_last_line(lines): |
4911 | """Fix last line if there is no new line. |
4912 | |
4913 | @@ -544,7 +544,7 @@ |
4914 | if last and last[-1] not in ('\r', '\n'): |
4915 | lines = lines[:-1] + [last+'\n'] |
4916 | return lines |
4917 | - |
4918 | + |
4919 | lines = [fix_last_line(l) for l in lines] |
4920 | if have_pygments: |
4921 | use_pygments = True |
4922 | @@ -570,7 +570,7 @@ |
4923 | else: |
4924 | use_pygments = False |
4925 | display_lines = lines |
4926 | - |
4927 | + |
4928 | def insertLine(cursor, line): |
4929 | if use_pygments: |
4930 | for ttype, value in line: |
4931 | @@ -579,12 +579,12 @@ |
4932 | cursor.insertText(value, format) |
4933 | else: |
4934 | cursor.insertText(line) |
4935 | - |
4936 | + |
4937 | def insertIxs(ixs): |
4938 | for cursor, line, ix in zip(cursors, display_lines, ixs): |
4939 | for l in line[ix[0]:ix[1]]: |
4940 | insertLine(cursor, l) |
4941 | - |
4942 | + |
4943 | def modifyFormatForTag (format, tag): |
4944 | if tag == "replace": |
4945 | format.setBackground(interline_changes_background) |
4946 | @@ -594,7 +594,7 @@ |
4947 | format.setBackground(brushes[tag][0]) |
4948 | else: |
4949 | format.setBackground(interline_changes_background) |
4950 | - |
4951 | + |
4952 | split_words = re.compile(r"\w+|\n\r|\r\n|\W") |
4953 | def insertIxsWithChangesHighlighted(ixs): |
4954 | texts = ["".join(l[ix[0]:ix[1]]) for l, ix in zip(lines, ixs)] |
4955 | @@ -602,9 +602,9 @@ |
4956 | # This is what the pygments lexer does, so we need to do the |
4957 | # same incase we have \r\n line endings. |
4958 | texts = ["\n".join(t.splitlines()) for t in texts] |
4959 | - |
4960 | + |
4961 | texts = [split_words.findall(t) for t in texts] |
4962 | - |
4963 | + |
4964 | if use_pygments: |
4965 | groups = ([], []) |
4966 | for tag, i0, i1, j0, j1 in SequenceMatcher(None, |
4967 | @@ -639,14 +639,14 @@ |
4968 | format = QtGui.QTextCharFormat() |
4969 | format.setFont(self.monospacedFont) |
4970 | modifyFormatForTag(format, tag) |
4971 | - |
4972 | + |
4973 | cursors[0].insertText("".join(texts[0][i0:i1]),format) |
4974 | cursors[1].insertText("".join(texts[1][j0:j1]),format) |
4975 | - |
4976 | + |
4977 | for cursor in cursors: |
4978 | cursor.setCharFormat (self.monospacedFormat) |
4979 | |
4980 | - |
4981 | + |
4982 | for i, group in enumerate(groups): |
4983 | if i > 0: |
4984 | y_top = [cursor.block().layout() for cursor in self.cursors] |
4985 | @@ -711,8 +711,8 @@ |
4986 | heights[i] = image.height() |
4987 | self.docs[i].addResource(QtGui.QTextDocument.ImageResource, |
4988 | QtCore.QUrl(file_id), |
4989 | - QtCore.QVariant(image)) |
4990 | - |
4991 | + image) |
4992 | + |
4993 | max_height = max(heights) |
4994 | for i, cursor in enumerate(self.cursors): |
4995 | format = QtGui.QTextBlockFormat() |
4996 | @@ -747,7 +747,7 @@ |
4997 | self.browsers[0].infoBlocks.append(l_block) |
4998 | self.browsers[1].infoBlocks.append(r_block) |
4999 | self.handle(1).infoBlocks.append((l_block, r_block)) |
5000 | - |
Awesome, this is great to see!
I'm not entirely sure how to go about reviewing this since it's so large - it exceeds the 5000 line limit from Launchpad. I don't think it's realistic to review everything in detail so perhaps we can just stick to the higher level bits.
Are you the author of all of the files that are being added, including e.g. the css files?