Use GTK3's GApplication/GtkApplication #178 (#181)

* Use GTK3's GApplication/GtkApplication #178
* fix: remove icons in menu
* doc: update CHANGELOG.md
* chore(i18n): update po/diffuse.pot

Co-authored-by: Yurii Zolotko <yurii.zolotko@pm.me>
Co-authored-by: Romain Failliot <romain.failliot@foolstep.com>
This commit is contained in:
Iurii Zolotko 2022-11-22 02:01:49 +07:00 committed by GitHub
parent c1cddb755b
commit 8e32f883ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 731 additions and 601 deletions

View File

@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Translation: updated Swedish translation (@eson57) - Translation: updated Swedish translation (@eson57)
- Dialog: prompt only once if several files needs to be reloaded (@yuriiz) - Dialog: prompt only once if several files needs to be reloaded (@yuriiz)
- Use GTK3's Gtk.Application/Gtk.ApplicationWindow (@yuriiz)
### Fixed ### Fixed

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-10-23 20:00-0400\n" "POT-Creation-Date: 2022-11-14 16:24-0500\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -42,604 +42,656 @@ msgstr ""
msgid "Copyright" msgid "Copyright"
msgstr "" msgstr ""
#: src/diffuse/dialogs.py:40 #: src/diffuse/dialogs.py:41
msgid "Diffuse is a graphical tool for merging and comparing text files." msgid "Diffuse is a graphical tool for merging and comparing text files."
msgstr "" msgstr ""
#: src/diffuse/dialogs.py:45 #: src/diffuse/dialogs.py:46
msgid "translator-credits" msgid "translator-credits"
msgstr "" msgstr ""
#: src/diffuse/dialogs.py:82 #: src/diffuse/dialogs.py:83
msgid "Encoding: " msgid "Encoding: "
msgstr "" msgstr ""
#: src/diffuse/dialogs.py:94 #: src/diffuse/dialogs.py:95
msgid "Revision: " msgid "Revision: "
msgstr "" msgstr ""
#: src/diffuse/dialogs.py:156 #: src/diffuse/dialogs.py:163
msgid "Find..." msgid "Find..."
msgstr "" msgstr ""
#: src/diffuse/dialogs.py:164 #: src/diffuse/dialogs.py:173
msgid "Search For: " msgid "Search For: "
msgstr "" msgstr ""
#: src/diffuse/dialogs.py:189 #: src/diffuse/dialogs.py:198
msgid "Match Case" msgid "Match Case"
msgstr "" msgstr ""
#: src/diffuse/dialogs.py:194 #: src/diffuse/dialogs.py:203
msgid "Search Backwards" msgid "Search Backwards"
msgstr "" msgstr ""
#: src/diffuse/main.py:85 #: src/diffuse/main.py:84
msgid "Close Tab" msgid "Close Tab"
msgstr "" msgstr ""
#: src/diffuse/main.py:132 #: src/diffuse/main.py:131
msgid "Open File..." msgid "Open File..."
msgstr "" msgstr ""
#: src/diffuse/main.py:133 #: src/diffuse/main.py:132
msgid "Reload File" msgid "Reload File"
msgstr "" msgstr ""
#: src/diffuse/main.py:134 #: src/diffuse/main.py:133
msgid "Save File" msgid "Save File"
msgstr "" msgstr ""
#: src/diffuse/main.py:135 #: src/diffuse/main.py:134
msgid "Save File As..." msgid "Save File As..."
msgstr "" msgstr ""
#: src/diffuse/main.py:217 #: src/diffuse/main.py:229
#, python-format #, python-format
msgid "Column %d" msgid "Column %d"
msgstr "" msgstr ""
#: src/diffuse/main.py:291 #: src/diffuse/main.py:303
msgid "Save changes before loading the new file?" msgid "Save changes before loading the new file?"
msgstr "" msgstr ""
#: src/diffuse/main.py:402 #: src/diffuse/main.py:414
#, python-format #, python-format
msgid "Error reading revision %(rev)s of %(file)s." msgid "Error reading revision %(rev)s of %(file)s."
msgstr "" msgstr ""
#: src/diffuse/main.py:405 src/diffuse/main.py:1860 #: src/diffuse/main.py:417 src/diffuse/main.py:2004
#, python-format #, python-format
msgid "Error reading %s." msgid "Error reading %s."
msgstr "" msgstr ""
#: src/diffuse/main.py:427 #: src/diffuse/main.py:439
msgid "Open File" msgid "Open File"
msgstr "" msgstr ""
#: src/diffuse/main.py:484 #: src/diffuse/main.py:492
#, python-format
msgid "The file %s changed on disk. Do you want to reload the file?"
msgstr ""
#: src/diffuse/main.py:510
#, python-format #, python-format
msgid "Save %(title)s Pane %(pane)d" msgid "Save %(title)s Pane %(pane)d"
msgstr "" msgstr ""
#: src/diffuse/main.py:542 #: src/diffuse/main.py:524
#, python-format #, python-format
msgid "A file named %s already exists. Do you want to overwrite it?" msgid "A file named %s already exists. Do you want to overwrite it?"
msgstr "" msgstr ""
#: src/diffuse/main.py:549 #: src/diffuse/main.py:531
#, python-format #, python-format
msgid "" msgid ""
"The file %s has been modified by another process since reading it. If you save, " "The file %s has been modified by another process since reading it. If you save, "
"all the external changes could be lost. Save anyways?" "all the external changes could be lost. Save anyways?"
msgstr "" msgstr ""
#: src/diffuse/main.py:591 #: src/diffuse/main.py:573
#, python-format #, python-format
msgid "Error encoding to %s." msgid "Error encoding to %s."
msgstr "" msgstr ""
#: src/diffuse/main.py:595 src/diffuse/preferences.py:300 #: src/diffuse/main.py:577 src/diffuse/preferences.py:300
#, python-format #, python-format
msgid "Error writing %s." msgid "Error writing %s."
msgstr "" msgstr ""
#: src/diffuse/main.py:625 #: src/diffuse/main.py:607
msgid "Go To Line..." msgid "Go To Line..."
msgstr "" msgstr ""
#: src/diffuse/main.py:626 #: src/diffuse/main.py:608
msgid "Line Number: " msgid "Line Number: "
msgstr "" msgstr ""
#: src/diffuse/main.py:657 #: src/diffuse/main.py:639
msgid "" msgid ""
"Press the enter key or double click to edit. Press the space bar or use the RMB " "Press the enter key or double click to edit. Press the space bar or use the RMB "
"menu to manually align." "menu to manually align."
msgstr "" msgstr ""
#: src/diffuse/main.py:661 #: src/diffuse/main.py:643
msgid "Press the escape key to finish editing." msgid "Press the escape key to finish editing."
msgstr "" msgstr ""
#: src/diffuse/main.py:664 #: src/diffuse/main.py:646
msgid "" msgid ""
"Select target line and press the space bar to align. Press the escape key to " "Select target line and press the space bar to align. Press the escape key to "
"cancel." "cancel."
msgstr "" msgstr ""
#: src/diffuse/main.py:787 #: src/diffuse/main.py:768
msgid "_File" msgid "_File"
msgstr "" msgstr ""
#: src/diffuse/main.py:788 #: src/diffuse/main.py:770
msgid "_Open File..." msgid "_Open File..."
msgstr "" msgstr ""
#: src/diffuse/main.py:789 #: src/diffuse/main.py:771
msgid "Open File In New _Tab..." msgid "Open File In New _Tab..."
msgstr "" msgstr ""
#: src/diffuse/main.py:790 #: src/diffuse/main.py:772
msgid "Open _Modified Files..." msgid "Open _Modified Files..."
msgstr "" msgstr ""
#: src/diffuse/main.py:791 #: src/diffuse/main.py:773
msgid "Open Commi_t..." msgid "Open Commi_t..."
msgstr "" msgstr ""
#: src/diffuse/main.py:792 #: src/diffuse/main.py:774
msgid "_Reload File" msgid "_Reload File"
msgstr "" msgstr ""
#: src/diffuse/main.py:794 #: src/diffuse/main.py:776
msgid "_Save File" msgid "_Save File"
msgstr "" msgstr ""
#: src/diffuse/main.py:795 #: src/diffuse/main.py:777
msgid "Save File _As..." msgid "Save File _As..."
msgstr "" msgstr ""
#: src/diffuse/main.py:796 #: src/diffuse/main.py:778
msgid "Save A_ll" msgid "Save A_ll"
msgstr "" msgstr ""
#: src/diffuse/main.py:798 #: src/diffuse/main.py:780
msgid "New _2-Way File Merge" msgid "New _2-Way File Merge"
msgstr "" msgstr ""
#: src/diffuse/main.py:799 #: src/diffuse/main.py:781
msgid "New _3-Way File Merge" msgid "New _3-Way File Merge"
msgstr "" msgstr ""
#: src/diffuse/main.py:800 #: src/diffuse/main.py:782
msgid "New _N-Way File Merge..." msgid "New _N-Way File Merge..."
msgstr "" msgstr ""
#: src/diffuse/main.py:802 #: src/diffuse/main.py:784
msgid "_Close Tab" msgid "_Close Tab"
msgstr "" msgstr ""
#: src/diffuse/main.py:803 #: src/diffuse/main.py:785
msgid "_Undo Close Tab" msgid "_Undo Close Tab"
msgstr "" msgstr ""
#: src/diffuse/main.py:804 #: src/diffuse/main.py:786
msgid "_Quit" msgid "_Quit"
msgstr "" msgstr ""
#: src/diffuse/main.py:807 #: src/diffuse/main.py:790
msgid "_Edit" msgid "_Edit"
msgstr "" msgstr ""
#: src/diffuse/main.py:808 #: src/diffuse/main.py:792
msgid "_Undo" msgid "_Undo"
msgstr "" msgstr ""
#: src/diffuse/main.py:809 #: src/diffuse/main.py:793
msgid "_Redo" msgid "_Redo"
msgstr "" msgstr ""
#: src/diffuse/main.py:811 #: src/diffuse/main.py:795
msgid "Cu_t" msgid "Cu_t"
msgstr "" msgstr ""
#: src/diffuse/main.py:812 #: src/diffuse/main.py:796
msgid "_Copy" msgid "_Copy"
msgstr "" msgstr ""
#: src/diffuse/main.py:813 #: src/diffuse/main.py:797
msgid "_Paste" msgid "_Paste"
msgstr "" msgstr ""
#: src/diffuse/main.py:815 #: src/diffuse/main.py:799
msgid "Select _All" msgid "Select _All"
msgstr "" msgstr ""
#: src/diffuse/main.py:816 #: src/diffuse/main.py:800
msgid "C_lear Edits" msgid "C_lear Edits"
msgstr "" msgstr ""
#: src/diffuse/main.py:817 #: src/diffuse/main.py:801
msgid "_Dismiss All Edits" msgid "_Dismiss All Edits"
msgstr "" msgstr ""
#: src/diffuse/main.py:819 #: src/diffuse/main.py:803
msgid "_Find..." msgid "_Find..."
msgstr "" msgstr ""
#: src/diffuse/main.py:820 #: src/diffuse/main.py:804
msgid "Find _Next" msgid "Find _Next"
msgstr "" msgstr ""
#: src/diffuse/main.py:821 #: src/diffuse/main.py:805
msgid "Find Pre_vious" msgid "Find Pre_vious"
msgstr "" msgstr ""
#: src/diffuse/main.py:822 #: src/diffuse/main.py:806
msgid "_Go To Line..." msgid "_Go To Line..."
msgstr "" msgstr ""
#: src/diffuse/main.py:824 #: src/diffuse/main.py:808
msgid "Pr_eferences..." msgid "Pr_eferences..."
msgstr "" msgstr ""
#: src/diffuse/main.py:828 #: src/diffuse/main.py:812
msgid "None" msgid "None"
msgstr "" msgstr ""
#: src/diffuse/main.py:846 #: src/diffuse/main.py:834
msgid "_View" msgid "_View"
msgstr "" msgstr ""
#: src/diffuse/main.py:847 #: src/diffuse/main.py:836
msgid "_Syntax Highlighting" msgid "_Syntax Highlighting"
msgstr "" msgstr ""
#: src/diffuse/main.py:849 #: src/diffuse/main.py:838
msgid "Re_align All" msgid "Re_align All"
msgstr "" msgstr ""
#: src/diffuse/main.py:850 #: src/diffuse/main.py:839
msgid "_Isolate" msgid "_Isolate"
msgstr "" msgstr ""
#: src/diffuse/main.py:852 #: src/diffuse/main.py:841
msgid "_First Difference" msgid "_First Difference"
msgstr "" msgstr ""
#: src/diffuse/main.py:853 #: src/diffuse/main.py:842
msgid "_Previous Difference" msgid "_Previous Difference"
msgstr "" msgstr ""
#: src/diffuse/main.py:854 #: src/diffuse/main.py:843
msgid "_Next Difference" msgid "_Next Difference"
msgstr "" msgstr ""
#: src/diffuse/main.py:855 #: src/diffuse/main.py:844
msgid "_Last Difference" msgid "_Last Difference"
msgstr "" msgstr ""
#: src/diffuse/main.py:857 #: src/diffuse/main.py:846
msgid "Fir_st Tab" msgid "Fir_st Tab"
msgstr "" msgstr ""
#: src/diffuse/main.py:858 #: src/diffuse/main.py:847
msgid "Pre_vious Tab" msgid "Pre_vious Tab"
msgstr "" msgstr ""
#: src/diffuse/main.py:859 #: src/diffuse/main.py:848
msgid "Next _Tab" msgid "Next _Tab"
msgstr "" msgstr ""
#: src/diffuse/main.py:860 #: src/diffuse/main.py:849
msgid "Las_t Tab" msgid "Las_t Tab"
msgstr "" msgstr ""
#: src/diffuse/main.py:862 #: src/diffuse/main.py:851
msgid "Shift Pane _Right" msgid "Shift Pane _Right"
msgstr "" msgstr ""
#: src/diffuse/main.py:863 #: src/diffuse/main.py:852
msgid "Shift Pane _Left" msgid "Shift Pane _Left"
msgstr "" msgstr ""
#: src/diffuse/main.py:866 #: src/diffuse/main.py:856
msgid "F_ormat" msgid "F_ormat"
msgstr "" msgstr ""
#: src/diffuse/main.py:867 #: src/diffuse/main.py:858
msgid "Convert To _Upper Case" msgid "Convert To _Upper Case"
msgstr "" msgstr ""
#: src/diffuse/main.py:868 #: src/diffuse/main.py:859
msgid "Convert To _Lower Case" msgid "Convert To _Lower Case"
msgstr "" msgstr ""
#: src/diffuse/main.py:870 #: src/diffuse/main.py:861
msgid "Sort Lines In _Ascending Order" msgid "Sort Lines In _Ascending Order"
msgstr "" msgstr ""
#: src/diffuse/main.py:871 #: src/diffuse/main.py:862
msgid "Sort Lines In D_escending Order" msgid "Sort Lines In D_escending Order"
msgstr "" msgstr ""
#: src/diffuse/main.py:873 #: src/diffuse/main.py:864
msgid "Remove Trailing _White Space" msgid "Remove Trailing _White Space"
msgstr "" msgstr ""
#: src/diffuse/main.py:874 #: src/diffuse/main.py:865
msgid "Convert Tabs To _Spaces" msgid "Convert Tabs To _Spaces"
msgstr "" msgstr ""
#: src/diffuse/main.py:875 #: src/diffuse/main.py:866
msgid "Convert Leading Spaces To _Tabs" msgid "Convert Leading Spaces To _Tabs"
msgstr "" msgstr ""
#: src/diffuse/main.py:877 #: src/diffuse/main.py:868
msgid "_Increase Indenting" msgid "_Increase Indenting"
msgstr "" msgstr ""
#: src/diffuse/main.py:878 #: src/diffuse/main.py:869
msgid "De_crease Indenting" msgid "De_crease Indenting"
msgstr "" msgstr ""
#: src/diffuse/main.py:880 #: src/diffuse/main.py:871
msgid "Convert To _DOS Format" msgid "Convert To _DOS Format"
msgstr "" msgstr ""
#: src/diffuse/main.py:881 #: src/diffuse/main.py:872
msgid "Convert To _Mac Format" msgid "Convert To _Mac Format"
msgstr "" msgstr ""
#: src/diffuse/main.py:882 #: src/diffuse/main.py:873
msgid "Convert To Uni_x Format" msgid "Convert To Uni_x Format"
msgstr "" msgstr ""
#: src/diffuse/main.py:885 #: src/diffuse/main.py:877
msgid "_Merge" msgid "_Merge"
msgstr "" msgstr ""
#: src/diffuse/main.py:886 #: src/diffuse/main.py:879
msgid "Copy Selection _Right" msgid "Copy Selection _Right"
msgstr "" msgstr ""
#: src/diffuse/main.py:887 #: src/diffuse/main.py:880
msgid "Copy Selection _Left" msgid "Copy Selection _Left"
msgstr "" msgstr ""
#: src/diffuse/main.py:889 #: src/diffuse/main.py:882
msgid "Copy Left _Into Selection" msgid "Copy Left _Into Selection"
msgstr "" msgstr ""
#: src/diffuse/main.py:890 #: src/diffuse/main.py:883
msgid "Copy Right I_nto Selection" msgid "Copy Right I_nto Selection"
msgstr "" msgstr ""
#: src/diffuse/main.py:891 #: src/diffuse/main.py:884
msgid "_Merge From Left Then Right" msgid "_Merge From Left Then Right"
msgstr "" msgstr ""
#: src/diffuse/main.py:892 #: src/diffuse/main.py:885
msgid "M_erge From Right Then Left" msgid "M_erge From Right Then Left"
msgstr "" msgstr ""
#: src/diffuse/main.py:895 #: src/diffuse/main.py:889
msgid "_Help" msgid "_Help"
msgstr "" msgstr ""
#: src/diffuse/main.py:896 #: src/diffuse/main.py:891
msgid "_Help Contents..." msgid "_Help Contents..."
msgstr "" msgstr ""
#: src/diffuse/main.py:898 #: src/diffuse/main.py:893
#, python-format #, python-format
msgid "_About %s..." msgid "_About %s..."
msgstr "" msgstr ""
#: src/diffuse/main.py:913 #: src/diffuse/main.py:908
msgid "New 2-Way File Merge" msgid "New 2-Way File Merge"
msgstr "" msgstr ""
#: src/diffuse/main.py:914 #: src/diffuse/main.py:909
msgid "New 3-Way File Merge" msgid "New 3-Way File Merge"
msgstr "" msgstr ""
#: src/diffuse/main.py:916 #: src/diffuse/main.py:911
msgid "Realign All" msgid "Realign All"
msgstr "" msgstr ""
#: src/diffuse/main.py:917 #: src/diffuse/main.py:912
msgid "First Difference" msgid "First Difference"
msgstr "" msgstr ""
#: src/diffuse/main.py:918 #: src/diffuse/main.py:913
msgid "Previous Difference" msgid "Previous Difference"
msgstr "" msgstr ""
#: src/diffuse/main.py:919 #: src/diffuse/main.py:914
msgid "Next Difference" msgid "Next Difference"
msgstr "" msgstr ""
#: src/diffuse/main.py:920 #: src/diffuse/main.py:915
msgid "Last Difference" msgid "Last Difference"
msgstr "" msgstr ""
#: src/diffuse/main.py:922 #: src/diffuse/main.py:917
msgid "Copy Selection Right" msgid "Copy Selection Right"
msgstr "" msgstr ""
#: src/diffuse/main.py:923 #: src/diffuse/main.py:918
msgid "Copy Selection Left" msgid "Copy Selection Left"
msgstr "" msgstr ""
#: src/diffuse/main.py:924 #: src/diffuse/main.py:919
msgid "Copy Left Into Selection" msgid "Copy Left Into Selection"
msgstr "" msgstr ""
#: src/diffuse/main.py:925 #: src/diffuse/main.py:920
msgid "Copy Right Into Selection" msgid "Copy Right Into Selection"
msgstr "" msgstr ""
#: src/diffuse/main.py:926 #: src/diffuse/main.py:921
msgid "Merge From Left Then Right" msgid "Merge From Left Then Right"
msgstr "" msgstr ""
#: src/diffuse/main.py:927 #: src/diffuse/main.py:922
msgid "Merge From Right Then Left" msgid "Merge From Right Then Left"
msgstr "" msgstr ""
#: src/diffuse/main.py:929 #: src/diffuse/main.py:924
msgid "Undo" msgid "Undo"
msgstr "" msgstr ""
#: src/diffuse/main.py:930 #: src/diffuse/main.py:925
msgid "Redo" msgid "Redo"
msgstr "" msgstr ""
#: src/diffuse/main.py:931 src/diffuse/widgets.py:1861 #: src/diffuse/main.py:926 src/diffuse/widgets.py:1861
msgid "Cut" msgid "Cut"
msgstr "" msgstr ""
#: src/diffuse/main.py:932 src/diffuse/widgets.py:1862 #: src/diffuse/main.py:927 src/diffuse/widgets.py:1862
msgid "Copy" msgid "Copy"
msgstr "" msgstr ""
#: src/diffuse/main.py:933 src/diffuse/widgets.py:1863 #: src/diffuse/main.py:928 src/diffuse/widgets.py:1863
msgid "Paste" msgid "Paste"
msgstr "" msgstr ""
#: src/diffuse/main.py:934 src/diffuse/widgets.py:1866 #: src/diffuse/main.py:929 src/diffuse/widgets.py:1866
msgid "Clear Edits" msgid "Clear Edits"
msgstr "" msgstr ""
#: src/diffuse/main.py:1057 #: src/diffuse/main.py:996
msgid "Changes detected"
msgstr ""
#: src/diffuse/main.py:1000
#, python-format
msgid ""
"The file \"%s\" changed on disk.\n"
"\n"
"Do you want to reload the file?"
msgstr ""
#: src/diffuse/main.py:1005
#, python-format
msgid ""
"The following files changed on disk:\n"
"%s\n"
"\n"
"Do you want to reload these files?"
msgstr ""
#: src/diffuse/main.py:1120
msgid "Some files have unsaved changes. Select the files to save before closing." msgid "Some files have unsaved changes. Select the files to save before closing."
msgstr "" msgstr ""
#: src/diffuse/main.py:1071 #: src/diffuse/main.py:1134
msgid "Tab" msgid "Tab"
msgstr "" msgstr ""
#: src/diffuse/main.py:1076 #: src/diffuse/main.py:1139
msgid "Pane" msgid "Pane"
msgstr "" msgstr ""
#: src/diffuse/main.py:1087 #: src/diffuse/main.py:1150
msgid "Close _Without Saving" msgid "Close _Without Saving"
msgstr "" msgstr ""
#: src/diffuse/main.py:1126 #: src/diffuse/main.py:1189
#, python-format #, python-format
msgid "Closing this tab will quit %s." msgid "Closing this tab will quit %s."
msgstr "" msgstr ""
#: src/diffuse/main.py:1209 #: src/diffuse/main.py:1266
#, python-format #, python-format
msgid "File Merge %d" msgid "File Merge %d"
msgstr "" msgstr ""
#: src/diffuse/main.py:1315 #: src/diffuse/main.py:1372
#, python-format #, python-format
msgid "Error retrieving commits for %s." msgid "Error retrieving commits for %s."
msgstr "" msgstr ""
#: src/diffuse/main.py:1347 #: src/diffuse/main.py:1404
#, python-format #, python-format
msgid "Error retrieving modifications for %s." msgid "Error retrieving modifications for %s."
msgstr "" msgstr ""
#: src/diffuse/main.py:1380 #: src/diffuse/main.py:1437
msgid "Open File In New Tab" msgid "Open File In New Tab"
msgstr "" msgstr ""
#: src/diffuse/main.py:1403 #: src/diffuse/main.py:1460
msgid "Choose Folder With Modified Files" msgid "Choose Folder With Modified Files"
msgstr "" msgstr ""
#: src/diffuse/main.py:1421 #: src/diffuse/main.py:1478
msgid "No modified files found." msgid "No modified files found."
msgstr "" msgstr ""
#: src/diffuse/main.py:1427 #: src/diffuse/main.py:1484
msgid "Choose Folder With Commit" msgid "Choose Folder With Commit"
msgstr "" msgstr ""
#: src/diffuse/main.py:1447 #: src/diffuse/main.py:1504
msgid "No committed files found." msgid "No committed files found."
msgstr "" msgstr ""
#: src/diffuse/main.py:1483 #: src/diffuse/main.py:1540
msgid "New N-Way File Merge..." msgid "New N-Way File Merge..."
msgstr "" msgstr ""
#: src/diffuse/main.py:1484 #: src/diffuse/main.py:1541
msgid "Number of panes: " msgid "Number of panes: "
msgstr "" msgstr ""
#: src/diffuse/main.py:1558 #: src/diffuse/main.py:1615
msgid "Phrase not found. Continue from the end of the file?" msgid "Phrase not found. Continue from the end of the file?"
msgstr "" msgstr ""
#: src/diffuse/main.py:1560 #: src/diffuse/main.py:1617
msgid "Phrase not found. Continue from the start of the file?" msgid "Phrase not found. Continue from the start of the file?"
msgstr "" msgstr ""
#: src/diffuse/main.py:1781 #: src/diffuse/main.py:1827
msgid "Do not read any resource files"
msgstr ""
#: src/diffuse/main.py:1835
msgid "Specify explicit resource file"
msgstr ""
#: src/diffuse/main.py:1843
msgid "File revisions <rev-1> and <rev>"
msgstr ""
#: src/diffuse/main.py:1851
msgid "Close all tabs with no differences"
msgstr ""
#: src/diffuse/main.py:1858
msgid "Use <codec> to read and write files"
msgstr ""
#: src/diffuse/main.py:1866
msgid "Display <label> instead of the file name"
msgstr ""
#: src/diffuse/main.py:1874
msgid "Create a new tab for each modified file"
msgstr ""
#: src/diffuse/main.py:1881
msgid "File revision <rev>"
msgstr ""
#: src/diffuse/main.py:1889
msgid "Create a new tab for each file"
msgstr ""
#: src/diffuse/main.py:1896
msgid "Start a new tab"
msgstr ""
#: src/diffuse/main.py:1903 src/diffuse/preferences.py:165
msgid "Version control system search order"
msgstr ""
#: src/diffuse/main.py:1911
msgid "Start with line <line> selected"
msgstr ""
#: src/diffuse/main.py:1919
msgid "Create a blank file comparison pane"
msgstr ""
#: src/diffuse/main.py:1926 src/diffuse/preferences.py:91
#: src/diffuse/preferences.py:100
msgid "Ignore changes to white space"
msgstr ""
#: src/diffuse/main.py:1933
msgid "Ignore changes in blank lines"
msgstr ""
#: src/diffuse/main.py:1940 src/diffuse/preferences.py:93
msgid "Ignore end of line differences"
msgstr ""
#: src/diffuse/main.py:1947 src/diffuse/preferences.py:89
msgid "Ignore case differences"
msgstr ""
#: src/diffuse/main.py:1954 src/diffuse/preferences.py:90
msgid "Ignore white space differences"
msgstr ""
#: src/diffuse/main.py:1957
msgid "" msgid ""
"Usage:\n"
" diffuse [OPTION...] [FILE...]\n"
" diffuse ( -h | -? | --help | -v | --version )\n"
"\n"
"Diffuse is a graphical tool for merging and comparing text files. Diffuse is\n" "Diffuse is a graphical tool for merging and comparing text files. Diffuse is\n"
"able to compare an arbitrary number of files side-by-side and gives users the\n" "able to compare an arbitrary number of files side-by-side and gives users the\n"
"ability to manually adjust line matching and directly edit files. Diffuse can\n" "ability to manually adjust line matching and directly edit files. Diffuse can\n"
"also retrieve revisions of files from several VCSs for comparison and merging.\n" "also retrieve revisions of files from several VCSs for comparison and merging."
"\n"
"Help Options:\n"
" ( -h | -? | --help ) Display this usage information\n"
" ( -v | --version ) Display version and copyright information\n"
"\n"
"Configuration Options:\n"
" --no-rcfile Do not read any resource files\n"
" --rcfile <file> Specify explicit resource file\n"
"\n"
"General Options:\n"
" ( -c | --commit ) <rev> File revisions <rev-1> and <rev>\n"
" ( -D | --close-if-same ) Close all tabs with no differences\n"
" ( -e | --encoding ) <codec> Use <codec> to read and write files\n"
" ( -L | --label ) <label> Display <label> instead of the file name\n"
" ( -m | --modified ) Create a new tab for each modified file\n"
" ( -r | --revision ) <rev> File revision <rev>\n"
" ( -s | --separate ) Create a new tab for each file\n"
" ( -t | --tab ) Start a new tab\n"
" ( -V | --vcs ) <vcs-list> Version control system search order\n"
" --line <line> Start with line <line> selected\n"
" --null-file Create a blank file comparison pane\n"
"\n"
"Display Options:\n"
" ( -b | --ignore-space-change ) Ignore changes to white space\n"
" ( -B | --ignore-blank-lines ) Ignore changes in blank lines\n"
" ( -E | --ignore-end-of-line ) Ignore end of line differences\n"
" ( -i | --ignore-case ) Ignore case differences\n"
" ( -w | --ignore-all-space ) Ignore white space differences"
msgstr "" msgstr ""
#: src/diffuse/main.py:1948 #: src/diffuse/main.py:2080
msgid "Error parsing line number." msgid "Error parsing line number."
msgstr "" msgstr ""
#: src/diffuse/main.py:1958 #: src/diffuse/main.py:2096
#, python-format
msgid "Skipping unknown argument \"%s\"."
msgstr ""
#: src/diffuse/main.py:1966
#, python-format #, python-format
msgid "Error processing argument \"%s\". Directory not expected." msgid "Error processing argument \"%s\". Directory not expected."
msgstr "" msgstr ""
@ -672,26 +724,10 @@ msgstr ""
msgid "Show white space characters" msgid "Show white space characters"
msgstr "" msgstr ""
#: src/diffuse/preferences.py:89
msgid "Ignore case differences"
msgstr ""
#: src/diffuse/preferences.py:90
msgid "Ignore white space differences"
msgstr ""
#: src/diffuse/preferences.py:91 src/diffuse/preferences.py:100
msgid "Ignore changes to white space"
msgstr ""
#: src/diffuse/preferences.py:92 #: src/diffuse/preferences.py:92
msgid "Ignore blank line differences" msgid "Ignore blank line differences"
msgstr "" msgstr ""
#: src/diffuse/preferences.py:93
msgid "Ignore end of line differences"
msgstr ""
#: src/diffuse/preferences.py:95 #: src/diffuse/preferences.py:95
msgid "Alignment" msgid "Alignment"
msgstr "" msgstr ""
@ -769,10 +805,6 @@ msgstr ""
msgid "Cygdrive prefix" msgid "Cygdrive prefix"
msgstr "" msgstr ""
#: src/diffuse/preferences.py:165
msgid "Version control system search order"
msgstr ""
#: src/diffuse/preferences.py:173 #: src/diffuse/preferences.py:173
msgid "\"co\" command" msgid "\"co\" command"
msgstr "" msgstr ""
@ -882,7 +914,7 @@ msgstr ""
msgid "Unhandled error at line {line} of {file}." msgid "Unhandled error at line {line} of {file}."
msgstr "" msgstr ""
#: src/diffuse/utils.py:66 #: src/diffuse/utils.py:65
msgid "Auto Detect" msgid "Auto Detect"
msgstr "" msgstr ""

View File

@ -38,7 +38,6 @@ from diffuse.utils import LineEnding
from diffuse.vcs.vcs_interface import VcsInterface from diffuse.vcs.vcs_interface import VcsInterface
from diffuse.vcs.vcs_registry import VcsRegistry from diffuse.vcs.vcs_registry import VcsRegistry
from diffuse.widgets import FileDiffViewerBase, EditMode from diffuse.widgets import FileDiffViewerBase, EditMode
from diffuse.widgets import createMenu
import gi # type: ignore import gi # type: ignore
gi.require_version('GObject', '2.0') gi.require_version('GObject', '2.0')
@ -47,8 +46,8 @@ gi.require_version('Gdk', '3.0')
gi.require_version('GdkPixbuf', '2.0') gi.require_version('GdkPixbuf', '2.0')
gi.require_version('Pango', '1.0') gi.require_version('Pango', '1.0')
gi.require_version('PangoCairo', '1.0') gi.require_version('PangoCairo', '1.0')
from gi.repository import GObject, Gtk, Gdk, GdkPixbuf, Pango # type: ignore # noqa: E402 from gi.repository import (Gdk, GdkPixbuf, Gio, # type: ignore # noqa: E402
GLib, GObject, Gtk, Pango)
theVCSs = VcsRegistry() theVCSs = VcsRegistry()
@ -121,7 +120,7 @@ class FileInfo:
# the main application class containing a set of file viewers # the main application class containing a set of file viewers
# this class displays tab for switching between viewers and dispatches menu # this class displays tab for switching between viewers and dispatches menu
# commands to the current viewer # commands to the current viewer
class Diffuse(Gtk.Window): class Diffuse(Gtk.ApplicationWindow):
# specialization of FileDiffViewerBase for Diffuse # specialization of FileDiffViewerBase for Diffuse
class FileDiffViewer(FileDiffViewerBase): class FileDiffViewer(FileDiffViewerBase):
# pane header # pane header
@ -665,8 +664,8 @@ class Diffuse(Gtk.Window):
def format_changed_cb(self, widget, f, fmt): def format_changed_cb(self, widget, f, fmt):
self.footers[f].setFormat(fmt) self.footers[f].setFormat(fmt)
def __init__(self, rc_dir): def __init__(self, rc_dir, *args, **kwargs):
super().__init__(type=Gtk.WindowType.TOPLEVEL) super().__init__(type=Gtk.WindowType.TOPLEVEL, *args, **kwargs)
self.prefs = Preferences(os.path.join(rc_dir, 'prefs')) self.prefs = Preferences(os.path.join(rc_dir, 'prefs'))
# number of created viewers (used to label some tabs) # number of created viewers (used to label some tabs)
@ -698,7 +697,6 @@ class Diffuse(Gtk.Window):
self.search_history: List[str] = [] self.search_history: List[str] = []
self.connect('delete-event', self.delete_cb) self.connect('delete-event', self.delete_cb)
accel_group = Gtk.AccelGroup()
# create a Box for our contents # create a Box for our contents
vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
@ -717,7 +715,7 @@ class Diffuse(Gtk.Window):
factory = Gtk.IconFactory() factory = Gtk.IconFactory()
# render the base item used to indicate a new document # render the base item used to indicate a new document
p0 = default_theme.load_icon_for_scale("document-new", icon_size, scale_factor, 0) p0 = default_theme.load_icon_for_scale('document-new', icon_size, scale_factor, 0)
w, h = p0.get_width(), p0.get_height() w, h = p0.get_width(), p0.get_height()
# render new 2-way merge icon # render new 2-way merge icon
@ -743,8 +741,8 @@ class Diffuse(Gtk.Window):
factory.add(DIFFUSE_STOCK_NEW_3WAY_MERGE, Gtk.IconSet.new_from_pixbuf(p)) factory.add(DIFFUSE_STOCK_NEW_3WAY_MERGE, Gtk.IconSet.new_from_pixbuf(p))
# render the left and right arrow we will use in our custom icons # render the left and right arrow we will use in our custom icons
p0 = default_theme.load_icon_for_scale("go-next", icon_size, scale_factor, 0) p0 = default_theme.load_icon_for_scale('go-next', icon_size, scale_factor, 0)
p1 = default_theme.load_icon_for_scale("go-previous", icon_size, scale_factor, 0) p1 = default_theme.load_icon_for_scale('go-previous', icon_size, scale_factor, 0)
w, h, s = p0.get_width(), p0.get_height(), 0.65 w, h, s = p0.get_width(), p0.get_height(), 0.65
sw, sh = int(s * w), int(s * h) sw, sh = int(s * w), int(s * h)
w1, h1 = w - sw, h - sh w1, h1 = w - sw, h - sh
@ -768,127 +766,141 @@ class Diffuse(Gtk.Window):
menuspecs = [] menuspecs = []
menuspecs.append([_('_File'), [ menuspecs.append([_('_File'), [
[_('_Open File...'), self.open_file_cb, None, Gtk.STOCK_OPEN, 'open_file'], [
[_('Open File In New _Tab...'), self.open_file_in_new_tab_cb, None, None, 'open_file_in_new_tab'], # noqa: E501 [_('_Open File...'), self.open_file_cb, None, 'open_file'],
[_('Open _Modified Files...'), self.open_modified_files_cb, None, None, 'open_modified_files'], # noqa: E501 [_('Open File In New _Tab...'), self.open_file_in_new_tab_cb, None, 'open_file_in_new_tab'], # noqa: E501
[_('Open Commi_t...'), self.open_commit_cb, None, None, 'open_commit'], [_('Open _Modified Files...'), self.open_modified_files_cb, None, 'open_modified_files'], # noqa: E501
[_('_Reload File'), self.reload_file_cb, None, Gtk.STOCK_REFRESH, 'reload_file'], [_('Open Commi_t...'), self.open_commit_cb, None, 'open_commit'],
[], [_('_Reload File'), self.reload_file_cb, None, 'reload_file'],
[_('_Save File'), self.save_file_cb, None, Gtk.STOCK_SAVE, 'save_file'], ], [
[_('Save File _As...'), self.save_file_as_cb, None, Gtk.STOCK_SAVE_AS, 'save_file_as'], [_('_Save File'), self.save_file_cb, None, 'save_file'],
[_('Save A_ll'), self.save_all_cb, None, None, 'save_all'], [_('Save File _As...'), self.save_file_as_cb, None, 'save_file_as'],
[], [_('Save A_ll'), self.save_all_cb, None, 'save_all'],
[_('New _2-Way File Merge'), self.new_2_way_file_merge_cb, None, DIFFUSE_STOCK_NEW_2WAY_MERGE, 'new_2_way_file_merge'], # noqa: E501 ], [
[_('New _3-Way File Merge'), self.new_3_way_file_merge_cb, None, DIFFUSE_STOCK_NEW_3WAY_MERGE, 'new_3_way_file_merge'], # noqa: E501 [_('New _2-Way File Merge'), self.new_2_way_file_merge_cb, None, 'new_2_way_file_merge'], # noqa: E501
[_('New _N-Way File Merge...'), self.new_n_way_file_merge_cb, None, None, 'new_n_way_file_merge'], # noqa: E501 [_('New _3-Way File Merge'), self.new_3_way_file_merge_cb, None, 'new_3_way_file_merge'], # noqa: E501
[], [_('New _N-Way File Merge...'), self.new_n_way_file_merge_cb, None, 'new_n_way_file_merge'], # noqa: E501
[_('_Close Tab'), self.close_tab_cb, None, Gtk.STOCK_CLOSE, 'close_tab'], ], [
[_('_Undo Close Tab'), self.undo_close_tab_cb, None, None, 'undo_close_tab'], [_('_Close Tab'), self.close_tab_cb, None, 'close_tab'],
[_('_Quit'), self.quit_cb, None, Gtk.STOCK_QUIT, 'quit'] [_('_Undo Close Tab'), self.undo_close_tab_cb, None, 'undo_close_tab'],
[_('_Quit'), self.quit_cb, None, 'quit']
]
]]) ]])
menuspecs.append([_('_Edit'), [ menuspecs.append([_('_Edit'), [
[_('_Undo'), self.button_cb, 'undo', Gtk.STOCK_UNDO, 'undo'], [
[_('_Redo'), self.button_cb, 'redo', Gtk.STOCK_REDO, 'redo'], [_('_Undo'), self.button_cb, 'undo', 'undo'],
[], [_('_Redo'), self.button_cb, 'redo', 'redo'],
[_('Cu_t'), self.button_cb, 'cut', Gtk.STOCK_CUT, 'cut'], ], [
[_('_Copy'), self.button_cb, 'copy', Gtk.STOCK_COPY, 'copy'], [_('Cu_t'), self.button_cb, 'cut', 'cut'],
[_('_Paste'), self.button_cb, 'paste', Gtk.STOCK_PASTE, 'paste'], [_('_Copy'), self.button_cb, 'copy', 'copy'],
[], [_('_Paste'), self.button_cb, 'paste', 'paste'],
[_('Select _All'), self.button_cb, 'select_all', None, 'select_all'], ], [
[_('C_lear Edits'), self.button_cb, 'clear_edits', Gtk.STOCK_CLEAR, 'clear_edits'], [_('Select _All'), self.button_cb, 'select_all', 'select_all'],
[_('_Dismiss All Edits'), self.button_cb, 'dismiss_all_edits', None, 'dismiss_all_edits'], # noqa: E501 [_('C_lear Edits'), self.button_cb, 'clear_edits', 'clear_edits'],
[], [_('_Dismiss All Edits'), self.button_cb, 'dismiss_all_edits', 'dismiss_all_edits'],
[_('_Find...'), self.find_cb, None, Gtk.STOCK_FIND, 'find'], ], [
[_('Find _Next'), self.find_next_cb, None, None, 'find_next'], [_('_Find...'), self.find_cb, None, 'find'],
[_('Find Pre_vious'), self.find_previous_cb, None, None, 'find_previous'], [_('Find _Next'), self.find_next_cb, None, 'find_next'],
[_('_Go To Line...'), self.go_to_line_cb, None, Gtk.STOCK_JUMP_TO, 'go_to_line'], [_('Find Pre_vious'), self.find_previous_cb, None, 'find_previous'],
[], [_('_Go To Line...'), self.go_to_line_cb, None, 'go_to_line'],
[_('Pr_eferences...'), self.preferences_cb, None, Gtk.STOCK_PREFERENCES, 'preferences'] ], [
[_('Pr_eferences...'), self.preferences_cb, None, 'preferences']
]
]]) ]])
submenudef = [ syntax_menu = [[[_('None'), None, '', 'syntax_highlighting']]]
[_('None'), self.syntax_cb, None, None, 'no_syntax_highlighting', True, None, ('syntax', None)] # noqa: E501
]
names = theResources.getSyntaxNames() names = theResources.getSyntaxNames()
variant = GLib.Variant.new_string('')
self.syntax_action = Gio.SimpleAction.new_stateful(
'syntax_highlighting', variant.get_type(), variant
)
self.syntax_action.connect('change-state', self.syntax_cb)
self.add_action(self.syntax_action)
if len(names) > 0: if len(names) > 0:
submenudef.append([]) syntax_section = []
names.sort(key=str.lower) names.sort(key=str.lower)
for name in names: for name in names:
submenudef.append([ syntax_section.append(
name, [
self.syntax_cb,
name, name,
None, None,
'syntax_highlighting_' + name, name,
True, 'syntax_highlighting',
None, ]
('syntax', name) )
]) syntax_menu.append(syntax_section)
menuspecs.append([_('_View'), [ menuspecs.append([_('_View'), [
[_('_Syntax Highlighting'), None, None, None, None, True, submenudef], [
[], [_('_Syntax Highlighting'), None, None, None, syntax_menu]
[_('Re_align All'), self.button_cb, 'realign_all', Gtk.STOCK_EXECUTE, 'realign_all'], ], [
[_('_Isolate'), self.button_cb, 'isolate', None, 'isolate'], [_('Re_align All'), self.button_cb, 'realign_all', 'realign_all'],
[], [_('_Isolate'), self.button_cb, 'isolate', 'isolate'],
[_('_First Difference'), self.button_cb, 'first_difference', Gtk.STOCK_GOTO_TOP, 'first_difference'], # noqa: E501 ], [
[_('_Previous Difference'), self.button_cb, 'previous_difference', Gtk.STOCK_GO_UP, 'previous_difference'], # noqa: E501 [_('_First Difference'), self.button_cb, 'first_difference', 'first_difference'],
[_('_Next Difference'), self.button_cb, 'next_difference', Gtk.STOCK_GO_DOWN, 'next_difference'], # noqa: E501 [_('_Previous Difference'), self.button_cb, 'previous_difference', 'previous_difference'], # noqa: E501
[_('_Last Difference'), self.button_cb, 'last_difference', Gtk.STOCK_GOTO_BOTTOM, 'last_difference'], # noqa: E501 [_('_Next Difference'), self.button_cb, 'next_difference', 'next_difference'],
[], [_('_Last Difference'), self.button_cb, 'last_difference', 'last_difference'],
[_('Fir_st Tab'), self.first_tab_cb, None, None, 'first_tab'], ], [
[_('Pre_vious Tab'), self.previous_tab_cb, None, None, 'previous_tab'], [_('Fir_st Tab'), self.first_tab_cb, None, 'first_tab'],
[_('Next _Tab'), self.next_tab_cb, None, None, 'next_tab'], [_('Pre_vious Tab'), self.previous_tab_cb, None, 'previous_tab'],
[_('Las_t Tab'), self.last_tab_cb, None, None, 'last_tab'], [_('Next _Tab'), self.next_tab_cb, None, 'next_tab'],
[], [_('Las_t Tab'), self.last_tab_cb, None, 'last_tab'],
[_('Shift Pane _Right'), self.button_cb, 'shift_pane_right', None, 'shift_pane_right'], ], [
[_('Shift Pane _Left'), self.button_cb, 'shift_pane_left', None, 'shift_pane_left'] [_('Shift Pane _Right'), self.button_cb, 'shift_pane_right', 'shift_pane_right'],
[_('Shift Pane _Left'), self.button_cb, 'shift_pane_left', 'shift_pane_left']
]
]]) ]])
menuspecs.append([_('F_ormat'), [ menuspecs.append([_('F_ormat'), [
[_('Convert To _Upper Case'), self.button_cb, 'convert_to_upper_case', None, 'convert_to_upper_case'], # noqa: E501 [
[_('Convert To _Lower Case'), self.button_cb, 'convert_to_lower_case', None, 'convert_to_lower_case'], # noqa: E501 [_('Convert To _Upper Case'), self.button_cb, 'convert_to_upper_case', 'convert_to_upper_case'], # noqa: E501
[], [_('Convert To _Lower Case'), self.button_cb, 'convert_to_lower_case', 'convert_to_lower_case'], # noqa: E501
[_('Sort Lines In _Ascending Order'), self.button_cb, 'sort_lines_in_ascending_order', Gtk.STOCK_SORT_ASCENDING, 'sort_lines_in_ascending_order'], # noqa: E501 ], [
[_('Sort Lines In D_escending Order'), self.button_cb, 'sort_lines_in_descending_order', Gtk.STOCK_SORT_DESCENDING, 'sort_lines_in_descending_order'], # noqa: E501 [_('Sort Lines In _Ascending Order'), self.button_cb, 'sort_lines_in_ascending_order', 'sort_lines_in_ascending_order'], # noqa: E501
[], [_('Sort Lines In D_escending Order'), self.button_cb, 'sort_lines_in_descending_order', 'sort_lines_in_descending_order'], # noqa: E501
[_('Remove Trailing _White Space'), self.button_cb, 'remove_trailing_white_space', None, 'remove_trailing_white_space'], # noqa: E501 ], [
[_('Convert Tabs To _Spaces'), self.button_cb, 'convert_tabs_to_spaces', None, 'convert_tabs_to_spaces'], # noqa: E501 [_('Remove Trailing _White Space'), self.button_cb, 'remove_trailing_white_space', 'remove_trailing_white_space'], # noqa: E501
[_('Convert Leading Spaces To _Tabs'), self.button_cb, 'convert_leading_spaces_to_tabs', None, 'convert_leading_spaces_to_tabs'], # noqa: E501 [_('Convert Tabs To _Spaces'), self.button_cb, 'convert_tabs_to_spaces', 'convert_tabs_to_spaces'], # noqa: E501
[], [_('Convert Leading Spaces To _Tabs'), self.button_cb, 'convert_leading_spaces_to_tabs', 'convert_leading_spaces_to_tabs'], # noqa: E501
[_('_Increase Indenting'), self.button_cb, 'increase_indenting', Gtk.STOCK_INDENT, 'increase_indenting'], # noqa: E501 ], [
[_('De_crease Indenting'), self.button_cb, 'decrease_indenting', Gtk.STOCK_UNINDENT, 'decrease_indenting'], # noqa: E501 [_('_Increase Indenting'), self.button_cb, 'increase_indenting', 'increase_indenting'], # noqa: E501
[], [_('De_crease Indenting'), self.button_cb, 'decrease_indenting', 'decrease_indenting'], # noqa: E501
[_('Convert To _DOS Format'), self.button_cb, 'convert_to_dos', None, 'convert_to_dos'], # noqa: E501 ], [
[_('Convert To _Mac Format'), self.button_cb, 'convert_to_mac', None, 'convert_to_mac'], # noqa: E501 [_('Convert To _DOS Format'), self.button_cb, 'convert_to_dos', 'convert_to_dos'],
[_('Convert To Uni_x Format'), self.button_cb, 'convert_to_unix', None, 'convert_to_unix'] # noqa: E501 [_('Convert To _Mac Format'), self.button_cb, 'convert_to_mac', 'convert_to_mac'],
[_('Convert To Uni_x Format'), self.button_cb, 'convert_to_unix', 'convert_to_unix']
]
]]) ]])
menuspecs.append([_('_Merge'), [ menuspecs.append([_('_Merge'), [
[_('Copy Selection _Right'), self.button_cb, 'copy_selection_right', Gtk.STOCK_GOTO_LAST, 'copy_selection_right'], # noqa: E501 [
[_('Copy Selection _Left'), self.button_cb, 'copy_selection_left', Gtk.STOCK_GOTO_FIRST, 'copy_selection_left'], # noqa: E501 [_('Copy Selection _Right'), self.button_cb, 'copy_selection_right', 'copy_selection_right'], # noqa: E501
[], [_('Copy Selection _Left'), self.button_cb, 'copy_selection_left', 'copy_selection_left'], # noqa: E501
[_('Copy Left _Into Selection'), self.button_cb, 'copy_left_into_selection', Gtk.STOCK_GO_FORWARD, 'copy_left_into_selection'], # noqa: E501 ], [
[_('Copy Right I_nto Selection'), self.button_cb, 'copy_right_into_selection', Gtk.STOCK_GO_BACK, 'copy_right_into_selection'], # noqa: E501 [_('Copy Left _Into Selection'), self.button_cb, 'copy_left_into_selection', 'copy_left_into_selection'], # noqa: E501
[_('_Merge From Left Then Right'), self.button_cb, 'merge_from_left_then_right', DIFFUSE_STOCK_LEFT_RIGHT, 'merge_from_left_then_right'], # noqa: E501 [_('Copy Right I_nto Selection'), self.button_cb, 'copy_right_into_selection', 'copy_right_into_selection'], # noqa: E501
[_('M_erge From Right Then Left'), self.button_cb, 'merge_from_right_then_left', DIFFUSE_STOCK_RIGHT_LEFT, 'merge_from_right_then_left'] # noqa: E501 [_('_Merge From Left Then Right'), self.button_cb, 'merge_from_left_then_right', 'merge_from_left_then_right'], # noqa: E501
[_('M_erge From Right Then Left'), self.button_cb, 'merge_from_right_then_left', 'merge_from_right_then_left'] # noqa: E501
]
]]) ]])
menuspecs.append([_('_Help'), [ menuspecs.append([_('_Help'), [
[_('_Help Contents...'), self.help_contents_cb, None, Gtk.STOCK_HELP, 'help_contents'], [
[], [_('_Help Contents...'), self.help_contents_cb, None, 'help_contents'],
[_('_About %s...') % (constants.APP_NAME, ), self.about_cb, None, Gtk.STOCK_ABOUT, 'about'] # noqa: E501 ], [
[_('_About %s...') % (constants.APP_NAME, ), self.about_cb, None, 'about']
]
]]) ]])
# used to disable menu events when switching tabs # used to disable menu events when switching tabs
self.menu_update_depth = 0 self.menu_update_depth = 0
# build list of radio menu items so we can update them to match the
# currently viewed pane menubar = Gio.Menu()
self.radio_menus = radio_menus = {} for label, sections in menuspecs:
menu_bar = _create_menu_bar(menuspecs, radio_menus, accel_group) menubar.append_submenu(label, self._create_menu(sections))
vbox.pack_start(menu_bar, False, False, 0) self.get_application().set_menubar(menubar)
menu_bar.show()
# create button bar # create button bar
hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=0) hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=0)
@ -933,11 +945,39 @@ class Diffuse(Gtk.Window):
vbox.pack_start(statusbar, False, False, 0) vbox.pack_start(statusbar, False, False, 0)
statusbar.show() statusbar.show()
self.add_accel_group(accel_group)
self.add(vbox) self.add(vbox)
vbox.show() vbox.show()
self.connect('focus-in-event', self.focus_in_cb) self.connect('focus-in-event', self.focus_in_cb)
def _create_menu(self, sections):
menu = Gio.Menu.new()
for section in sections:
section_menu = Gio.Menu.new()
for label, cb, cb_data, accel, *submenu in section:
if submenu:
(submenu,) = submenu
section_menu.append_submenu(label, self._create_menu(submenu))
else:
if cb_data is not None:
cb_data = GLib.Variant.new_string(cb_data)
accel = accel.replace('_', '-')
if cb is not None:
action = Gio.SimpleAction.new(accel, cb_data and cb_data.get_type())
action.connect('activate', cb)
self.add_action(action)
item = Gio.MenuItem.new(label)
item.set_action_and_target_value('win.' + accel, cb_data)
key_binding = theResources.getKeyBindings('menu', accel)
if len(key_binding) > 0:
key, modifier = key_binding[0]
self.get_application().set_accels_for_action(
Gio.Action.print_detailed_name('win.' + accel, cb_data),
[Gtk.accelerator_name(key, modifier)],
)
section_menu.append_item(item)
menu.append_section(None, section_menu)
return menu
# notifies all viewers on focus changes so they may check for external # notifies all viewers on focus changes so they may check for external
# changes to files # changes to files
def focus_in_cb(self, widget, event): def focus_in_cb(self, widget, event):
@ -955,18 +995,18 @@ class Diffuse(Gtk.Window):
filename = h.info.label if h.info.label is not None else h.info.name filename = h.info.label if h.info.label is not None else h.info.name
filenames.append(filename) filenames.append(filename)
primary_text = _("Changes detected") primary_text = _('Changes detected')
secondary_text = "" secondary_text = ''
if len(filenames) == 1: if len(filenames) == 1:
secondary_text = _( secondary_text = _(
"The file \"%s\" changed on disk.\n\n" 'The file "%s" changed on disk.\n\n'
"Do you want to reload the file?" 'Do you want to reload the file?'
) % (filenames[0],) ) % (filenames[0],)
else: else:
secondary_text = _( secondary_text = _(
"The following files changed on disk:\n%s\n\n" 'The following files changed on disk:\n%s\n\n'
"Do you want to reload these files?" 'Do you want to reload these files?'
) % ("\n".join("- " + filename for filename in filenames),) ) % ('\n'.join('- ' + filename for filename in filenames),)
dialog = Gtk.MessageDialog( dialog = Gtk.MessageDialog(
transient_for=self.get_toplevel(), transient_for=self.get_toplevel(),
@ -1041,7 +1081,7 @@ class Diffuse(Gtk.Window):
ss.append(f'{k} {v}\n') ss.append(f'{k} {v}\n')
ss.sort() ss.sort()
f = open(statepath, 'w') f = open(statepath, 'w')
f.write(f"# This state file was generated by {constants.APP_NAME} {constants.VERSION}.\n\n") # noqa: E501 f.write(f'# This state file was generated by {constants.APP_NAME} {constants.VERSION}.\n\n') # noqa: E501
for s in ss: for s in ss:
f.write(s) f.write(s)
f.close() f.close()
@ -1194,13 +1234,7 @@ class Diffuse(Gtk.Window):
# update the label in the status bar # update the label in the status bar
def setSyntax(self, s): def setSyntax(self, s):
# update menu # update menu
t = self.radio_menus.get('syntax', None) self.syntax_action.set_state(GLib.Variant.new_string(s or ''))
if t is not None:
t = t[1]
if s in t:
self.menu_update_depth += 1
t[s].set_active(True)
self.menu_update_depth -= 1
# callback used when switching notebook pages # callback used when switching notebook pages
def switch_page_cb(self, widget, ptr, page_num): def switch_page_cb(self, widget, ptr, page_num):
@ -1387,7 +1421,7 @@ class Diffuse(Gtk.Window):
# respond to close window request from the window manager # respond to close window request from the window manager
def delete_cb(self, widget, event): def delete_cb(self, widget, event):
if self.confirmQuit(): if self.confirmQuit():
Gtk.main_quit() self.get_application().quit()
return False return False
return True return True
@ -1534,7 +1568,7 @@ class Diffuse(Gtk.Window):
# callback for the quit menu item # callback for the quit menu item
def quit_cb(self, widget, data): def quit_cb(self, widget, data):
if self.confirmQuit(): if self.confirmQuit():
Gtk.main_quit() self.get_application().quit()
# request search parameters if force=True and then perform a search in the # request search parameters if force=True and then perform a search in the
# current viewer pane # current viewer pane
@ -1644,7 +1678,7 @@ class Diffuse(Gtk.Window):
# callback for most menu items and buttons # callback for most menu items and buttons
def button_cb(self, widget, data): def button_cb(self, widget, data):
self.getCurrentViewer().button_cb(widget, data) self.getCurrentViewer().button_cb(widget, data.get_string())
# display help documentation # display help documentation
def help_contents_cb(self, widget, data): def help_contents_cb(self, widget, data):
@ -1711,18 +1745,6 @@ class Diffuse(Gtk.Window):
dialog.destroy() dialog.destroy()
# convenience method for creating a menu bar according to a template
def _create_menu_bar(specs, radio, accel_group):
menu_bar = Gtk.MenuBar()
for label, spec in specs:
menu = Gtk.MenuItem.new_with_mnemonic(label)
menu.set_submenu(createMenu(spec, radio, accel_group))
menu.set_use_underline(True)
menu.show()
menu_bar.append(menu)
return menu_bar
# convenience method for packing buttons into a container according to a # convenience method for packing buttons into a container according to a
# template # template
def _append_buttons(box, size, specs): def _append_buttons(box, size, specs):
@ -1789,56 +1811,176 @@ GObject.signal_new('save', Diffuse.FileDiffViewer.PaneHeader, GObject.SignalFlag
GObject.signal_new('save-as', Diffuse.FileDiffViewer.PaneHeader, GObject.SignalFlags.RUN_LAST, GObject.TYPE_NONE, ()) # noqa: E501 GObject.signal_new('save-as', Diffuse.FileDiffViewer.PaneHeader, GObject.SignalFlags.RUN_LAST, GObject.TYPE_NONE, ()) # noqa: E501
def main(version, sysconfigdir): class Application(Gtk.Application):
# app = Application() def __init__(self, sysconfigdir, *args, **kwargs):
# return app.run(sys.argv) super().__init__(
*args,
application_id='io.github.mightycreak.Diffuse',
flags=Gio.ApplicationFlags.HANDLES_COMMAND_LINE | Gio.ApplicationFlags.NON_UNIQUE,
**kwargs,
)
args = sys.argv self.sysconfigdir = sysconfigdir
argc = len(args)
constants.VERSION = version self.add_main_option(
'version',
if argc == 2 and args[1] in ['-v', '--version']: ord('v'),
print('%s %s\n%s' % (constants.APP_NAME, constants.VERSION, constants.COPYRIGHT)) GLib.OptionFlags.NONE,
return 0 GLib.OptionArg.NONE,
_('Display version and copyright information'),
if argc == 2 and args[1] in ['-h', '-?', '--help']: None,
print(_('''Usage: )
diffuse [OPTION...] [FILE...] self.add_main_option(
diffuse ( -h | -? | --help | -v | --version ) 'no-rcfile',
0,
Diffuse is a graphical tool for merging and comparing text files. Diffuse is GLib.OptionFlags.NONE,
GLib.OptionArg.NONE,
_('Do not read any resource files'),
None,
)
self.add_main_option(
'rcfile',
0,
GLib.OptionFlags.NONE,
GLib.OptionArg.STRING,
_('Specify explicit resource file'),
'file',
)
self.add_main_option(
'commit',
ord('c'),
GLib.OptionFlags.NONE,
GLib.OptionArg.STRING,
_('File revisions <rev-1> and <rev>'),
'rev',
)
self.add_main_option(
'close-if-same',
ord('D'),
GLib.OptionFlags.NONE,
GLib.OptionArg.NONE,
_('Close all tabs with no differences'),
)
self.add_main_option(
'encoding',
ord('e'),
GLib.OptionFlags.NONE,
GLib.OptionArg.STRING,
_('Use <codec> to read and write files'),
'codec',
)
self.add_main_option(
'label',
ord('L'),
GLib.OptionFlags.NONE,
GLib.OptionArg.STRING,
_('Display <label> instead of the file name'),
'label',
)
self.add_main_option(
'modified',
ord('m'),
GLib.OptionFlags.NONE,
GLib.OptionArg.NONE,
_('Create a new tab for each modified file'),
)
self.add_main_option(
'revision',
ord('r'),
GLib.OptionFlags.NONE,
GLib.OptionArg.STRING,
_('File revision <rev>'),
'rev',
)
self.add_main_option(
'separate',
ord('s'),
GLib.OptionFlags.NONE,
GLib.OptionArg.NONE,
_('Create a new tab for each file'),
)
self.add_main_option(
'tab',
ord('t'),
GLib.OptionFlags.NONE,
GLib.OptionArg.NONE,
_('Start a new tab'),
)
self.add_main_option(
'vcs',
ord('V'),
GLib.OptionFlags.NONE,
GLib.OptionArg.STRING,
_('Version control system search order'),
'vcs-list',
)
self.add_main_option(
'line',
0,
GLib.OptionFlags.NONE,
GLib.OptionArg.STRING,
_('Start with line <line> selected'),
'line',
)
self.add_main_option(
'null-file',
0,
GLib.OptionFlags.NONE,
GLib.OptionArg.NONE,
_('Create a blank file comparison pane'),
)
self.add_main_option(
'ignore-space-change',
ord('b'),
GLib.OptionFlags.NONE,
GLib.OptionArg.NONE,
_('Ignore changes to white space'),
)
self.add_main_option(
'ignore-blank-lines',
ord('B'),
GLib.OptionFlags.NONE,
GLib.OptionArg.NONE,
_('Ignore changes in blank lines'),
)
self.add_main_option(
'ignore-end-of-line',
ord('E'),
GLib.OptionFlags.NONE,
GLib.OptionArg.NONE,
_('Ignore end of line differences'),
)
self.add_main_option(
'ignore-case',
ord('i'),
GLib.OptionFlags.NONE,
GLib.OptionArg.NONE,
_('Ignore case differences'),
)
self.add_main_option(
'ignore-all-space',
ord('w'),
GLib.OptionFlags.NONE,
GLib.OptionArg.NONE,
_('Ignore white space differences'),
)
self.set_option_context_summary(_(
'''Diffuse is a graphical tool for merging and comparing text files. Diffuse is
able to compare an arbitrary number of files side-by-side and gives users the able to compare an arbitrary number of files side-by-side and gives users the
ability to manually adjust line matching and directly edit files. Diffuse can ability to manually adjust line matching and directly edit files. Diffuse can
also retrieve revisions of files from several VCSs for comparison and merging. also retrieve revisions of files from several VCSs for comparison and merging.'''
))
Help Options: def do_activate(self):
( -h | -? | --help ) Display this usage information self.window.present()
( -v | --version ) Display version and copyright information
Configuration Options: def do_command_line(self, command_line):
--no-rcfile Do not read any resource files options = command_line.get_options_dict()
--rcfile <file> Specify explicit resource file # convert GVariantDict -> GVariant -> dict
options = options.end().unpack()
General Options: if 'version' in options:
( -c | --commit ) <rev> File revisions <rev-1> and <rev> print('%s %s\n%s' % (constants.APP_NAME, constants.VERSION, constants.COPYRIGHT))
( -D | --close-if-same ) Close all tabs with no differences
( -e | --encoding ) <codec> Use <codec> to read and write files
( -L | --label ) <label> Display <label> instead of the file name
( -m | --modified ) Create a new tab for each modified file
( -r | --revision ) <rev> File revision <rev>
( -s | --separate ) Create a new tab for each file
( -t | --tab ) Start a new tab
( -V | --vcs ) <vcs-list> Version control system search order
--line <line> Start with line <line> selected
--null-file Create a blank file comparison pane
Display Options:
( -b | --ignore-space-change ) Ignore changes to white space
( -B | --ignore-blank-lines ) Ignore changes in blank lines
( -E | --ignore-end-of-line ) Ignore end of line differences
( -i | --ignore-case ) Ignore case differences
( -w | --ignore-all-space ) Ignore white space differences'''))
return 0 return 0
# find the config directory and create it if it didn't exist # find the config directory and create it if it didn't exist
@ -1848,7 +1990,6 @@ Display Options:
rc_dir = os.path.expanduser('~') rc_dir = os.path.expanduser('~')
subdirs.insert(0, '.config') subdirs.insert(0, '.config')
rc_dir = utils.make_subdirs(rc_dir, subdirs) rc_dir = utils.make_subdirs(rc_dir, subdirs)
# find the local data directory and create it if it didn't exist # find the local data directory and create it if it didn't exist
data_dir = os.environ.get('XDG_DATA_HOME', None) data_dir = os.environ.get('XDG_DATA_HOME', None)
subdirs = ['diffuse'] subdirs = ['diffuse']
@ -1856,25 +1997,19 @@ Display Options:
data_dir = os.path.expanduser('~') data_dir = os.path.expanduser('~')
subdirs[:0] = ['.local', 'share'] subdirs[:0] = ['.local', 'share']
data_dir = utils.make_subdirs(data_dir, subdirs) data_dir = utils.make_subdirs(data_dir, subdirs)
# load resource files # load resource files
i = 1
rc_files = [] rc_files = []
if i < argc and args[i] == '--no-rcfile': if 'no-rcfile' not in options:
i += 1
elif i + 1 < argc and args[i] == '--rcfile':
i += 1
rc_files.append(args[i])
i += 1
else:
# parse system wide then personal initialization files # parse system wide then personal initialization files
if utils.isWindows(): if utils.isWindows():
rc_file = os.path.join(utils.bin_dir, 'diffuserc') rc_file = os.path.join(utils.bin_dir, 'diffuserc')
else: else:
rc_file = os.path.join(utils.bin_dir, f'{sysconfigdir}/diffuserc') rc_file = os.path.join(utils.bin_dir, self.sysconfigdir, 'diffuserc')
for rc_file in rc_file, os.path.join(rc_dir, 'diffuserc'): for rc_file in rc_file, os.path.join(rc_dir, 'diffuserc'):
if os.path.isfile(rc_file): if os.path.isfile(rc_file):
rc_files.append(rc_file) rc_files.append(rc_file)
if 'rcfile' in options:
rc_files.append(options['rcfile'])
for rc_file in rc_files: for rc_file in rc_files:
# convert to absolute path so the location of any processing errors are # convert to absolute path so the location of any processing errors are
# reported with normalized file names # reported with normalized file names
@ -1882,14 +2017,11 @@ Display Options:
try: try:
theResources.parse(rc_file) theResources.parse(rc_file)
except IOError: except IOError:
utils.logError(_('Error reading %s.') % (rc_file, )) utils.logError(_('Error reading %s.') % (rc_file,))
self.window = diff = Diffuse(rc_dir, application=self)
diff = Diffuse(rc_dir)
# load state # load state
statepath = os.path.join(data_dir, 'state') self.statepath = os.path.join(data_dir, 'state')
diff.loadState(statepath) self.window.loadState(self.statepath)
# process remaining command line arguments # process remaining command line arguments
encoding = None encoding = None
revs = [] revs = []
@ -1901,77 +2033,68 @@ Display Options:
'modified': diff.createModifiedFileTabs, 'modified': diff.createModifiedFileTabs,
'commit': diff.createCommitFileTabs, 'commit': diff.createCommitFileTabs,
'separate': diff.createSeparateTabs, 'separate': diff.createSeparateTabs,
'single': diff.createSingleTab 'single': diff.createSingleTab,
} }
mode = 'single' mode = 'single'
options = {} opts = {}
while i < argc: if 'commit' in options:
arg = args[i]
if len(arg) > 0 and arg[0] == '-':
if i + 1 < argc and arg in ['-c', '--commit']:
# specified revision # specified revision
funcs[mode](specs, labels, options) funcs[mode](specs, labels, options)
i += 1 specs, labels, opts = [], [], {'commit': options['commit']}
specs, labels, options = [], [], {'commit': args[i]}
mode = 'commit' mode = 'commit'
elif arg in ['-D', '--close-if-same']: if 'close-if-same' in options:
close_on_same = True close_on_same = True
elif i + 1 < argc and arg in ['-e', '--encoding']: if 'encoding' in options:
i += 1 encoding = options['encoding']
encoding = args[i]
encoding = encodings.aliases.aliases.get(encoding, encoding) encoding = encodings.aliases.aliases.get(encoding, encoding)
elif arg in ['-m', '--modified']: if 'modified' in options:
funcs[mode](specs, labels, options) funcs[mode](specs, labels, opts)
specs, labels, options = [], [], {} specs, labels, opts = [], [], {}
mode = 'modified' mode = 'modified'
elif i + 1 < argc and arg in ['-r', '--revision']: if 'revision' in options:
# specified revision # specified revision
i += 1 revs.append((options['revision'], encoding))
revs.append((args[i], encoding)) if 'separate' in options:
elif arg in ['-s', '--separate']: funcs[mode](specs, labels, opts)
funcs[mode](specs, labels, options) specs, labels, opts = [], [], {}
specs, labels, options = [], [], {}
# open items in separate tabs # open items in separate tabs
mode = 'separate' mode = 'separate'
elif arg in ['-t', '--tab']: if 'tab' in options:
funcs[mode](specs, labels, options) funcs[mode](specs, labels, opts)
specs, labels, options = [], [], {} specs, labels, opts = [], [], {}
# start a new tab # start a new tab
mode = 'single' mode = 'single'
elif i + 1 < argc and arg in ['-V', '--vcs']: if 'vcs' in options:
i += 1 diff.prefs.setString('vcs_search_order', options['vcs'])
diff.prefs.setString('vcs_search_order', args[i])
diff.preferences_updated() diff.preferences_updated()
elif arg in ['-b', '--ignore-space-change']: if 'ignore-space-change' in options:
diff.prefs.setBool('display_ignore_whitespace_changes', True) diff.prefs.setBool('display_ignore_whitespace_changes', True)
diff.prefs.setBool('align_ignore_whitespace_changes', True) diff.prefs.setBool('align_ignore_whitespace_changes', True)
diff.preferences_updated() diff.preferences_updated()
elif arg in ['-B', '--ignore-blank-lines']: if 'ignore-blank-lines' in options:
diff.prefs.setBool('display_ignore_blanklines', True) diff.prefs.setBool('display_ignore_blanklines', True)
diff.prefs.setBool('align_ignore_blanklines', True) diff.prefs.setBool('align_ignore_blanklines', True)
diff.preferences_updated() diff.preferences_updated()
elif arg in ['-E', '--ignore-end-of-line']: if 'ignore-end-of-line' in options:
diff.prefs.setBool('display_ignore_endofline', True) diff.prefs.setBool('display_ignore_endofline', True)
diff.prefs.setBool('align_ignore_endofline', True) diff.prefs.setBool('align_ignore_endofline', True)
diff.preferences_updated() diff.preferences_updated()
elif arg in ['-i', '--ignore-case']: if 'ignore-case' in options:
diff.prefs.setBool('display_ignore_case', True) diff.prefs.setBool('display_ignore_case', True)
diff.prefs.setBool('align_ignore_case', True) diff.prefs.setBool('align_ignore_case', True)
diff.preferences_updated() diff.preferences_updated()
elif arg in ['-w', '--ignore-all-space']: if 'ignore-all-space' in options:
diff.prefs.setBool('display_ignore_whitespace', True) diff.prefs.setBool('display_ignore_whitespace', True)
diff.prefs.setBool('align_ignore_whitespace', True) diff.prefs.setBool('align_ignore_whitespace', True)
diff.preferences_updated() diff.preferences_updated()
elif i + 1 < argc and arg == '-L': if 'label' in options:
i += 1 labels.append(options['label'])
labels.append(args[i]) if 'line' in options:
elif i + 1 < argc and arg == '--line':
i += 1
try: try:
options['line'] = int(args[i]) opts['line'] = int(options['line'])
except ValueError: except ValueError:
utils.logError(_('Error parsing line number.')) utils.logError(_('Error parsing line number.'))
elif arg == '--null-file': if 'null-file' in options:
# add a blank file pane # add a blank file pane
if mode == 'single' or mode == 'separate': if mode == 'single' or mode == 'separate':
if len(revs) == 0: if len(revs) == 0:
@ -1979,17 +2102,14 @@ Display Options:
specs.append((None, revs)) specs.append((None, revs))
revs = [] revs = []
had_specs = True had_specs = True
else: for arg in command_line.get_arguments()[1:]:
utils.logError(_('Skipping unknown argument "%s".') % (args[i], )) filename = diff.prefs.convertToNativePath(arg)
else:
filename = diff.prefs.convertToNativePath(args[i])
if (mode == 'single' or mode == 'separate') and os.path.isdir(filename): if (mode == 'single' or mode == 'separate') and os.path.isdir(filename):
if len(specs) > 0: if len(specs) > 0:
filename = os.path.join(filename, os.path.basename(specs[-1][0])) filename = os.path.join(filename, os.path.basename(specs[-1][0]))
else: else:
utils.logError(_( utils.logError(
'Error processing argument "%s". Directory not expected.') % (args[i], ) _('Error processing argument "%s". Directory not expected.') % (arg,))
)
filename = None filename = None
if filename is not None: if filename is not None:
if len(revs) == 0: if len(revs) == 0:
@ -1997,12 +2117,10 @@ Display Options:
specs.append((filename, revs)) specs.append((filename, revs))
revs = [] revs = []
had_specs = True had_specs = True
i += 1
if mode in ['modified', 'commit'] and len(specs) == 0: if mode in ['modified', 'commit'] and len(specs) == 0:
specs.append((os.curdir, [(None, encoding)])) specs.append((os.curdir, [(None, encoding)]))
had_specs = True had_specs = True
funcs[mode](specs, labels, options) funcs[mode](specs, labels, opts)
# create a file diff viewer if the command line arguments haven't # create a file diff viewer if the command line arguments haven't
# implicitly created any # implicitly created any
if not had_specs: if not had_specs:
@ -2014,9 +2132,12 @@ Display Options:
if n > 0: if n > 0:
nb.set_show_tabs(diff.prefs.getBool('tabs_always_show') or n > 1) nb.set_show_tabs(diff.prefs.getBool('tabs_always_show') or n > 1)
nb.get_nth_page(0).grab_focus() nb.get_nth_page(0).grab_focus()
diff.show() self.activate()
Gtk.main()
# save state
diff.saveState(statepath)
return 0 return 0
def main(version, sysconfigdir):
constants.VERSION = version
app = Application(sysconfigdir)
return app.run(sys.argv)

View File

@ -1853,23 +1853,44 @@ class FileDiffViewerBase(Gtk.Grid):
can_select = self.mode in (EditMode.LINE, EditMode.CHAR) and f == self.current_pane can_select = self.mode in (EditMode.LINE, EditMode.CHAR) and f == self.current_pane
can_swap = (f != self.current_pane) can_swap = (f != self.current_pane)
menu = createMenu([ menu = self._create_menu([
[_('Align with Selection'), self.align_with_selection_cb, [f, i], Gtk.STOCK_EXECUTE, None, can_align], # noqa: E501 [_('Align with Selection'), self.align_with_selection_cb, [f, i], Gtk.STOCK_EXECUTE, can_align], # noqa: E501
[_('Isolate'), self.button_cb, 'isolate', None, None, can_isolate], [_('Isolate'), self.button_cb, 'isolate', None, can_isolate],
[_('Merge Selection'), self.merge_lines_cb, f, None, None, can_merge], [_('Merge Selection'), self.merge_lines_cb, f, None, can_merge],
[], [],
[_('Cut'), self.button_cb, 'cut', Gtk.STOCK_CUT, None, can_select], [_('Cut'), self.button_cb, 'cut', Gtk.STOCK_CUT, can_select],
[_('Copy'), self.button_cb, 'copy', Gtk.STOCK_COPY, None, can_select], [_('Copy'), self.button_cb, 'copy', Gtk.STOCK_COPY, can_select],
[_('Paste'), self.button_cb, 'paste', Gtk.STOCK_PASTE, None, can_select], [_('Paste'), self.button_cb, 'paste', Gtk.STOCK_PASTE, can_select],
[], [],
[_('Select All'), self.button_cb, 'select_all', None, None, can_select], [_('Select All'), self.button_cb, 'select_all', None, can_select],
[_('Clear Edits'), self.button_cb, 'clear_edits', Gtk.STOCK_CLEAR, None, can_isolate], # noqa: E501 [_('Clear Edits'), self.button_cb, 'clear_edits', Gtk.STOCK_CLEAR, can_isolate], # noqa: E501
[], [],
[_('Swap with Selected Pane'), self.swap_panes_cb, f, None, None, can_swap] [_('Swap with Selected Pane'), self.swap_panes_cb, f, None, can_swap]
]) ])
menu.attach_to_widget(self) menu.attach_to_widget(self)
menu.popup(None, None, None, None, event.button, event.time) menu.popup(None, None, None, None, event.button, event.time)
@staticmethod
def _create_menu(specs):
menu = Gtk.Menu()
for spec in specs:
if len(spec) > 0:
(label, cb, cb_data, image_stock_name, sensitive) = spec
item = Gtk.ImageMenuItem.new_with_mnemonic(label)
item.set_use_underline(True)
item.set_sensitive(sensitive)
if image_stock_name is not None:
image = Gtk.Image()
image.set_from_stock(image_stock_name, Gtk.IconSize.MENU)
item.set_image(image)
if cb is not None:
item.connect('activate', cb, cb_data)
else:
item = Gtk.SeparatorMenuItem()
item.show()
menu.append(item)
return menu
# callback used to notify us about click and drag motion # callback used to notify us about click and drag motion
def darea_motion_notify_cb(self, widget, event, f): def darea_motion_notify_cb(self, widget, event, f):
if event.state & Gdk.ModifierType.BUTTON1_MASK: if event.state & Gdk.ModifierType.BUTTON1_MASK:
@ -3708,51 +3729,6 @@ class FileDiffViewerBase(Gtk.Grid):
self._mergeBoth(True) self._mergeBoth(True)
# convenience method for creating a menu according to a template
def createMenu(specs, radio=None, accel_group=None):
menu = Gtk.Menu()
for spec in specs:
if len(spec) > 0:
if len(spec) > 7 and spec[7] is not None:
g, k = spec[7]
if g not in radio:
item = Gtk.RadioMenuItem.new_with_mnemonic_from_widget(None, spec[0])
radio[g] = (item, {})
else:
item = Gtk.RadioMenuItem.new_with_mnemonic_from_widget(radio[g][0], spec[0])
radio[g][1][k] = item
else:
item = Gtk.ImageMenuItem.new_with_mnemonic(spec[0])
cb = spec[1]
if cb is not None:
data = spec[2]
item.connect('activate', cb, data)
if len(spec) > 3 and spec[3] is not None:
image = Gtk.Image()
image.set_from_stock(spec[3], Gtk.IconSize.MENU)
item.set_image(image)
if accel_group is not None and len(spec) > 4:
a = theResources.getKeyBindings('menu', spec[4])
if len(a) > 0:
key, modifier = a[0]
item.add_accelerator(
'activate',
accel_group,
key,
modifier,
Gtk.AccelFlags.VISIBLE)
if len(spec) > 5:
item.set_sensitive(spec[5])
if len(spec) > 6 and spec[6] is not None:
item.set_submenu(createMenu(spec[6], radio, accel_group))
item.set_use_underline(True)
else:
item = Gtk.SeparatorMenuItem()
item.show()
menu.append(item)
return menu
class CharacterClass(IntFlag): class CharacterClass(IntFlag):
ALPHANUMERIC = 0 ALPHANUMERIC = 0
WHITESPACE = 1 WHITESPACE = 1