Compare commits

...

48 Commits

Author SHA1 Message Date
itdominator b36121c1c5 Merge github.com:gnome-terminator/terminator into feature/guake-like-functionality 2024-04-12 15:04:16 -05:00
Matt Rose bad3bda058
Merge pull request #898 from arrowd/patch-1
Install manpages to share/man on FreeBSD
2024-03-25 20:32:44 -04:00
Gleb Popov 4062cddb1f
Install manpages to share/man on FreeBSD 2024-03-25 22:22:57 +03:00
Matt Rose 3c0abdf6d6
Merge pull request #895 from mattrose/865-file-links-not-clickable-if-the-root-dir-has-a-underscore
Properly parse file:/// URIs
2024-03-13 21:08:30 -04:00
Matt Rose 4e6e293771 Properly parse file:/// URIs
Previously, file URIs were lumped in with full uris that would be
used for HTTP, FTP, etc.  This caused file:/// uri parser to ignore
any file with a root dir that had a character that was not a valid
hostname character to be ignored.
2024-03-11 15:17:51 -04:00
Matt Rose 51e3bd2519
Merge pull request #886 from mattrose/fix-syntaxwarning
fix syntax warnings
2024-02-18 10:30:57 -05:00
Matt Rose 66427862d6
Merge pull request #887 from mattrose/fix-tb
fix traceback in layout_done
2024-02-18 10:30:29 -05:00
Matt Rose 5ef1131791
Merge pull request #856 from vssdeo/852-terminator_py_get_focussed_terminal_always_returns_none
[bug 852] - 852-terminator_py_get_focussed_terminal_always_returns_none
2024-02-18 10:22:32 -05:00
Matt Rose 67e9f3c5c3
Merge pull request #844 from vssdeo/843-Plugin-SaveLastSessionLayout-not-saving-layout-when-user-logs-out-or-shutdown-or-restart
[bug 843] 843-Plugin-SaveLastSessionLayout-not-saving-layout-when-use…
2024-02-17 10:19:03 -05:00
Matt Rose 9b9682be8b
Merge pull request #878 from markdoerr/feature/save-user-session
feat: plugin - Save current user layout of all sessions, fixes #563
2024-02-17 09:58:59 -05:00
Matt Rose ea33815955
Merge pull request #863 from gnome-terminator/translations_po-terminator-pot--master_ru
Updates for file po/terminator.pot in ru
2024-02-17 09:37:51 -05:00
mark doerr 5d0904b619 fix: version re-set to 2.1.3 2024-02-16 19:36:41 +01:00
Matt Rose 3bf1a7a5f4
Merge pull request #855 from vssdeo/846-mouseless-keyboard-url-open-fails-to-extract-text-and-clear-search-between-commands
846 mouseless keyboard url open fails to extract text and clear search between commands
2024-02-15 22:30:15 -05:00
Matt Rose 594537f9ed
Merge pull request #849 from vssdeo/835-crash-after-unzooming-a-single-terminal-inside-a-tab
[bug 835] 835-crash-after-unzooming-a-single-terminal-inside-a-tab #835
2024-02-15 22:28:29 -05:00
Matt Rose 3ed6ea7d16
Merge pull request #875 from AtomsForPeace/fix-reload-config
add missing @with_proxy, fixes #850
2024-02-15 22:19:58 -05:00
Matt Rose 7f581fde86 fix traceback in layout_done
Got this while testing layouts.  Easy fix

Traceback (most recent call last):
  File "/home/mattrose/Code/terminator/./terminator", line 137, in <module>
    TERMINATOR.layout_done()
  File "/home/mattrose/Code/terminator/terminatorlib/terminator.py", line 341, in layout_done
    term.ensure_visible_and_focussed()
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'ensure_visible_and_focussed'
2024-02-15 22:16:44 -05:00
Matt Rose 36b3602292 fix syntax warnings
Got the following Warnings when running under python 3.12.1

home/mattrose/Code/terminator/terminatorlib/terminal.py:324: SyntaxWarning: invalid escape sequence '\['
  hostchars = "-A-Za-z0-9:\[\]"
/home/mattrose/Code/terminator/terminatorlib/terminal.py:348: SyntaxWarning: invalid escape sequence '\.'
  "(www|ftp)[" + hostchars + "]*\.[" + hostchars +
/home/mattrose/Code/terminator/terminatorlib/terminal.py:354: SyntaxWarning: invalid escape sequence '\.'
  "[a-zA-Z0-9-]*\.[a-zA-Z0-9][a-zA-Z0-9-]+" +
/home/mattrose/Code/terminator/terminatorlib/terminal.py:359: SyntaxWarning: invalid escape sequence '\^'
  """news:[-A-Z\^_a-z{|}~!"#$%&'()*+,./0-9;:=?`]+@""" +

To fix this, I changed the strings to raw strings to pass to the regex
2024-02-15 21:47:11 -05:00
Matt Rose 750a9be85a
Merge pull request #882 from vssdeo/760-working-directory-feature-is-broken
[bug 760] working directory feature is broken
2024-02-14 21:34:29 -05:00
Matt Rose d9aaa549c5
Merge pull request #883 from rcalixte/fix_groupwindow
window.py: Fix window group toggle keybind
2024-02-11 15:51:39 -05:00
Rick Calixte 46f956613f
window.py: Fix window group toggle keybind
The current conditional always evaluates to False, resulting in the
ungroup_win() function never being called
2024-02-09 18:39:37 -05:00
Matt Rose 5c6fda2513
Merge pull request #841 from vssdeo/706-Favorites-Bookmarks-Plugin
706 favorites bookmarks plugin
2024-02-08 21:02:20 -05:00
Matt Rose 9a3b8997db
Merge pull request #884 from mattrose/ask_before_close_gui
Ask before close gui
2024-02-08 20:02:00 -05:00
Matt Rose aa03c235b6 wired up preferences GUI 2024-02-08 16:34:02 -05:00
Matt Rose 305f6b2881 GUI designed 2024-02-08 16:02:41 -05:00
Matt Rose b47f7d073e
Merge pull request #834 from Vulcalien/ask-before-closing
Ask before closing, even if there is only one terminal
2024-02-08 15:49:18 -05:00
Vishweshwar Saran Singh Deo 4519b3e631 [bug 760] working directory feature is broken
- as per the bug the layout does not get updated when "Save" button in layout is pressed
- it does get updated if the window is closed by pressing top x close icon.
- on pressing Save, it seems that the prefseditor takes this from current_layout = terminator.describe_layout() and saves it in config
- whereas the current changes are done per key stroke and config is updated
- this patch copies the parameters like directory and command when Save is press and on_layoutrefreshbutton_clicked() is called
- Hence working dir and command are copied when Save is pressed using uuid to match terminals.
- If there is a command registered then the terminal runs the command and exits. so one is not able to see the results.
2024-02-05 22:35:26 +05:30
Matt Rose 94254eecf1
Merge pull request #824 from j-d-r/master
Fix: Add CLI command to reload configuration
2024-02-05 10:43:55 -05:00
Matt Rose b13d35649b
Merge pull request #822 from vssdeo/802-Ability-to-undo-or-restore-changes-to-the-preferences
[bug 802] - Ability to undo or restore changes to the preferences #802
2024-02-05 10:32:21 -05:00
Matt Rose e9ef0745af
Merge pull request #753 from nautics889/issue-752-remove-unused-imports
fix: Remove unused imports in several modules #752
2024-02-05 09:48:28 -05:00
mark doerr d36f148a26 feat: plugin - save current user layout 2024-02-03 12:26:15 +01:00
nautics889 6651b30fde fix: Remove unused imports in several modules #752
Removed unused imports in:
* terminator
* terminatorlib/plugins/dir_open.py
* terminatorlib/terminal.py
* terminatorlib/terminal_popup_menu.py
* terminatorlib/terminator.py
* tests/test_signalman.py
2024-01-26 20:20:19 +02:00
Matt Rose 6d5cd041b3
Merge pull request #756 from gotmax23/no-pytest-runner
remove deprecated pytest-runner
2024-01-26 11:19:21 -05:00
atomsforpeace a28c5db7cf add missing @with_proxy, fixes #850 2024-01-26 15:17:41 +01:00
transifex-integration[bot] 3e7145034a
Translate po/terminator.pot in ru
100% translated source file: 'po/terminator.pot'
on 'ru'.
2023-11-22 11:24:25 +00:00
Vishweshwar Saran Singh Deo 03e5769bd1 [bug 852] - 852-terminator_py_get_focussed_terminal_always_returns_none
- added get_vte().has_focus() for a valid focussed terminal to return
2023-10-26 23:38:59 +05:30
Vishweshwar Saran Singh Deo b052da7efc [bug 846] 846-mouseless-keyboard-url-open-fails-to-extract-text-and-clear-search-between-commands #846
- this includes the changes in #835 since its required to decouple
- made plugin dependent on focus-in and removed tab-change
- plugin is now decoupled from main terminator code
2023-10-24 11:34:03 +05:30
Vishweshwar Saran Singh Deo c7c9fd0d4b [bug 835] 835-crash-after-unzooming-a-single-terminal-inside-a-tab #835
- removing the tab-change event dependency and having a simpler solution with focus-in
2023-10-24 10:14:19 +05:30
Vishweshwar Saran Singh Deo ff45920874 [bug 835] 835-crash-after-unzooming-a-single-terminal-inside-a-tab #835
-removed previous code to start fresh
-added event type for tab-change since other way of identifying zoomed widget was not simple and clear
-emit tab-change is done at a single point now in notebook.py
2023-10-20 23:50:25 +05:30
Vishweshwar Saran Singh Deo 9000327973 [bug 843] 843-Plugin-SaveLastSessionLayout-not-saving-layout-when-user-logs-out-or-shutdown-or-restart #843
- fixed Plugin SaveLastSessionLayout not saving layout when user logs out or shutdown or restart
- signals added
2023-10-17 19:49:57 +05:30
Vishweshwar Saran Singh Deo a5ddcbe255 [bug 706] 706-Favorites-Bookmarks-Plugin #706
- the dialog window taking command for bookmark via shortcut keybinding will have focus on OK Button for faster interaction
- fixed a transient window issue for loading pref window via shortcut and context menu
- filed new command text area  was getting filled with last command
- fixed list store init
2023-10-17 01:11:21 +05:30
Vulcalien 8c0c7ceb4f Add a setting to specify when to ask to confirm before closing
'ask_before_closing' replaces 'suppress_multiple_term_dialog'.
The function 'Container.construct_confirm_close' was significantly
modified. The terminator_config manpage has been updated.
2023-10-10 17:03:21 +02:00
Vulcalien 8911723518 Window: always ask confirmation to close, even with only one terminal 2023-10-10 15:47:39 +02:00
Vishweshwar Saran Singh Deo 86337ad326 [bug 706] 706-Favorites-Bookmarks-Plugin #706
- modified custom command plugin to have bookmarks
- added keybindings for directly adding or launch the custom command menu
- made name parsing of the custom command optional
2023-10-08 12:40:19 +05:30
itdominator 9248fc9340 Re-adding guake like functionality comit after bungled merge 2023-09-18 21:49:07 -05:00
Julien Dusser b935eda987 [bug 827] fix --new-tab and --toggle-visibility
Commit 2e1dd1f add a 'if' between a 'if' and 'else' breaking logic.
2023-09-18 18:15:48 +02:00
Vishweshwar Saran Singh Deo 6fc6d7f658 [bug 802] 802-Ability-to-undo-or-restore-changes-to-the-preferences #802
- fixed the errors in case of missing configs
- restore file is stored in writable path
2023-09-11 18:30:02 +05:30
Vishweshwar Saran Singh Deo 2fe3ad8b08 [bug 802] - Ability to undo or restore changes to the preferences #802
- added basic config restore option from preferences window
 - changes to glade made in addition to addition of destory signal
 - minor cleaup in config to have a single function return confilg filename via get_config_filename
2023-09-04 17:21:37 +05:30
Maxwell G de48b07328
remove deprecated pytest-runner
See https://github.com/pytest-dev/pytest-runner/#deprecation-notice. We
can call pytest directly instead.
2023-05-07 05:25:27 +00:00
24 changed files with 908 additions and 441 deletions

View File

@ -41,13 +41,11 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e .
python setup.py develop
pip install -e '.[test]'
- name: Compile all scripts
run: python -m compileall -f terminatorlib/ tests/ remotinator terminator
- name: Run tests
run: |
pip install -e '.[test]'
xvfb-run -a python setup.py test
xvfb-run -a pytest

View File

@ -90,6 +90,30 @@ Specify the preferred size and position of Terminator\(cqs window;
see \fBX\fP(7).
.RE
.sp
\fB\-\-guake\-key\fP=\fIGUAKE_KEY\fP
.RS 4
A Guake like terminal mode where terminal can be toggled by a key.
Usage Example: terminator \-\-guake\-key="F8" \-\-guake\-side left \-\-guake\-width 700 \-\-guake\-height 800
.RE
.sp
\fB\-\-guake\-side\fP=\fIGUAKE_SIDE\fP
.RS 4
Set the preferred screen edge position of a terminal in Guake like mode.
Options: top, bottom, left, right
Default: top
.RE
.sp
\fB\-\-guake\-width\fP=\fIGUAKE_WIDTH\fP
.RS 4
Set the preferred width when using Guake like mode.
Default: 800
.RE
.sp
\fB\-\-guake\-height\fP=\fIGUAKE_HEIGHT\fP
.RS 4
Set the preferred height when using Guake like mode.
Default: 600
.sp
\fB\-e\fP \fICOMMAND\fP, \fB\-\-command\fP=\fICOMMAND\fP
.RS 4
Run the specified command instead of the default shell or profile

View File

@ -1,13 +1,13 @@
'\" t
.\" Title: terminator_config
.\" Author: [see the "AUTHOR(S)" section]
.\" Generator: Asciidoctor 2.0.18
.\" Date: 2023-04-22
.\" Generator: Asciidoctor 2.0.16
.\" Date: 2023-10-10
.\" Manual: Manual for Terminator
.\" Source: Terminator
.\" Language: English
.\"
.TH "TERMINATOR_CONFIG" "5" "2023-04-22" "Terminator" "Manual for Terminator"
.TH "TERMINATOR_CONFIG" "5" "2023-10-10" "Terminator" "Manual for Terminator"
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.ss \n[.ss] 0
@ -130,12 +130,11 @@ If set to True, the window will resize in step with font sizes.
Default value: \fBFalse\fP
.RE
.sp
\fBsuppress_multiple_term_dialog\fP = \fIboolean\fP
\fBask_before_closing\fP = \fIstring\fP
.RS 4
If set to True, Terminator will ask for confirmation when closing
multiple terminals.
.br
Default value: \fBFalse\fP
Specify when to ask for confirmation before closing a window or a tab.
Can be any of: \*(Aqalways\*(Aq, \*(Aqmultiple_terminals\*(Aq, \*(Aqnever\*(Aq.
Default value: \fBmultiple_terminals\fP
.RE
.sp
\fBborderless\fP = \fIboolean\fP

View File

@ -2,7 +2,7 @@
:doctype: manpage
:manmanual: Manual for Terminator
:mansource: Terminator
:revdate: 2023-04-22
:revdate: 2023-10-10
:docdate: {revdate}
== NAME
@ -90,10 +90,10 @@ Default value: *False*
If set to True, the window will resize in step with font sizes. +
Default value: *False*
*suppress_multiple_term_dialog* = _boolean_::
If set to True, Terminator will ask for confirmation when closing
multiple terminals. +
Default value: *False*
*ask_before_closing* = _string_::
Specify when to ask for confirmation before closing a window or a tab.
Can be any of: 'always', 'multiple_terminals', 'never'.
Default value: *multiple_terminals*
// --- Window appearance ---

341
po/ru.po
View File

@ -2,27 +2,25 @@
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#
# Translators:
# Gnome Terminator <terminator@lazyfrosch.de>, 2020
#
# Mariya Shikunova <mariia@basealt.ru>, 2023
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-01-22 00:51+0100\n"
"POT-Creation-Date: 2022-10-19 09:29-0400\n"
"PO-Revision-Date: 2020-04-22 08:11+0000\n"
"Last-Translator: Gnome Terminator <terminator@lazyfrosch.de>, 2020\n"
"Language-Team: Russian (https://www.transifex.com/terminator/teams/109338/"
"ru/)\n"
"Language: ru\n"
"Last-Translator: Mariya Shikunova <mariia@basealt.ru>, 2023\n"
"Language-Team: Russian (https://app.transifex.com/terminator/teams/109338/ru/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n"
"%100>=11 && n%100<=14)? 2 : 3);\n"
"Language: ru\n"
"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);\n"
#. Command uuid req. Description
#: ../remotinator.py:39
@ -47,7 +45,7 @@ msgstr "Вывести список всех терминалов"
#: ../remotinator.py:44
msgid "Get the uuid of the current focused terminal"
msgstr ""
msgstr "Вывести UUID текущего терминала"
#: ../remotinator.py:45
msgid "Get the UUID of a parent window"
@ -67,23 +65,23 @@ msgstr "Вывести заголовок родительской вкладк
#: ../remotinator.py:49
msgid "Set the title of a parent tab"
msgstr ""
msgstr "Указать заголовок родительской вкладки"
#: ../remotinator.py:50
msgid "Set the background image"
msgstr ""
msgstr "Указать фоновое изображение"
#: ../remotinator.py:51
msgid "Set the background image for all terminals"
msgstr ""
msgstr "Указать фоновое изображение для всех терминалов"
#: ../remotinator.py:52
msgid "Switch current terminal profile"
msgstr ""
msgstr "Переключиться на профиль текущего терминала"
#: ../remotinator.py:53
msgid "Switch profile of all currently running terminals"
msgstr ""
msgstr "Переключиться на профиль всех текущих запущенных терминалов"
#: ../remotinator.py:70
#, python-format
@ -112,23 +110,24 @@ msgstr ""
#: ../remotinator.py:80
msgid "Profile name to switch to"
msgstr ""
msgstr "Имя профиля для переключения"
#: ../remotinator.py:83
msgid "File to pass to command"
msgstr ""
msgstr "Файл для передачи команде"
#: ../remotinator.py:86
msgid "Command to run in new terminal"
msgstr ""
msgstr "Команда для выполнения в новом терминале"
#: ../remotinator.py:89
msgid "Tab name to set. Only used with \"set_tab_title\" command."
msgstr ""
"Имя вкладки для установки. Используется только с командой «set_tab_title»."
#: ../remotinator.py:92
msgid "Tab name to set."
msgstr ""
msgstr "Имя вкладки для установки."
#: ../data/terminator.desktop.in.h:1 ../data/terminator.appdata.xml.in.h:1
#: ../terminatorlib/plugins/activitywatch.py:83
@ -150,9 +149,14 @@ msgstr "Технологии будущего для терминалов"
msgid ""
"A power-user tool for arranging terminals. It is inspired by programs such "
"as gnome-multi-term, quadkonsole, etc. in that the main focus is arranging "
"terminals in grids (tabs is the most common default method, which Terminator "
"also supports)."
"terminals in grids (tabs is the most common default method, which Terminator"
" also supports)."
msgstr ""
"Удобный инструмент для настройки терминалов. На его создание вдохновили "
"такие программы, как gnome-multi-term и quadkonsole, в которых основное "
"внимание уделяется размещению терминалов в виде сетки (наиболее "
"распространённый метод по умолчанию — вкладки, который также поддерживается "
"в Terminator)"
#: ../data/terminator.appdata.xml.in.h:5
msgid ""
@ -161,6 +165,10 @@ msgid ""
"out in different directions with useful features for sysadmins and other "
"users."
msgstr ""
"Большая часть поведения Terminator основана на GNOME Terminal, и со временем"
" в приложение добавляется всё больше функций из него, однако также есть "
"планы по расширению Terminator в разных направлениях с помощью полезных "
"функций для системных администраторов и других пользователей."
#: ../data/terminator.appdata.xml.in.h:6
msgid "Some highlights:"
@ -180,7 +188,7 @@ msgstr "Перетаскивание и изменение порядка тер
#: ../data/terminator.appdata.xml.in.h:10
msgid "Lots of keyboard shortcuts"
msgstr "Множество сочетаний клавиш быстрого доступа"
msgstr "Множество комбинаций клавиш быстрого доступа"
#: ../data/terminator.appdata.xml.in.h:11
msgid "Save multiple layouts and profiles via GUI preferences editor"
@ -225,7 +233,7 @@ msgid ""
"This window has several terminals open. Closing the window will also close "
"all terminals within it."
msgstr ""
"Это окно имеет несколько запущенных терминалов. Закрытие окна повлечет за "
"Это окно имеет несколько запущенных терминалов. Закрытие окна повлечёт за "
"собой так же и их закрытие."
#: ../terminatorlib/container.py:178
@ -233,8 +241,8 @@ msgid ""
"This tab has several terminals open. Closing the tab will also close all "
"terminals within it."
msgstr ""
"Эта вкладка имеет несколько запущенных терминалов. Ее закрытие повлечет за "
"собой так же и их закрытие."
"Эта вкладка имеет несколько запущенных терминалов. Её закрытие повлечёт за "
"собой также и их закрытие."
#: ../terminatorlib/container.py:198
msgid "Do not show this message next time"
@ -299,8 +307,8 @@ msgid ""
"Use the rest of the command line as a command to execute inside the "
"terminal, and its arguments"
msgstr ""
"Использовать для выполнения в терминале остаток командной строки как команду "
"и её аргументы"
"Использовать для выполнения в терминале остаток командной строки как команду"
" и её аргументы"
#: ../terminatorlib/optionparse.py:69
msgid "Specify a config file"
@ -308,7 +316,7 @@ msgstr "Укажите файл конфигурации"
#: ../terminatorlib/optionparse.py:71
msgid "Specify a partial config json file"
msgstr ""
msgstr "Укажите частичный json-файл конфигурации"
#: ../terminatorlib/optionparse.py:76
msgid "Set the working directory"
@ -316,7 +324,8 @@ msgstr "Установить рабочий каталог"
#: ../terminatorlib/optionparse.py:77
msgid "Set a custom icon for the window (by file or name)"
msgstr "Установить пользовательский значок для этого окна (по файлу или имени)"
msgstr ""
"Установить пользовательский значок для этого окна (по файлу или имени)"
#: ../terminatorlib/optionparse.py:80
msgid "Set a custom WM_WINDOW_ROLE property on the window"
@ -352,19 +361,19 @@ msgstr "Разделенный запятыми список методов дл
#: ../terminatorlib/optionparse.py:96
msgid "If Terminator is already running, just open a new tab"
msgstr "Если Терминатор уже запущен, просто откройте новую вкладку"
msgstr "Если Terminator уже запущен, просто откройте новую вкладку"
#: ../terminatorlib/optionparse.py:98
msgid "If Terminator is already running, just unhide all hidden windows"
msgstr ""
msgstr "Если Terminator уже запущен, раскройте все скрытые окна"
#: ../terminatorlib/optionparse.py:100
msgid "List all profiles"
msgstr ""
msgstr "Вывести список всех профилей"
#: ../terminatorlib/optionparse.py:102
msgid "List all layouts"
msgstr ""
msgstr "Вывести список всех компоновок"
#: ../terminatorlib/plugins/activitywatch.py:54
msgid "Watch for _activity"
@ -482,7 +491,7 @@ msgstr "Название *%s* уже существует"
#: ../terminatorlib/plugins/dir_open.py:26
msgid "Open current directory"
msgstr ""
msgstr "Открыть текущий каталог"
#: ../terminatorlib/plugins/logger.py:21
#: ../terminatorlib/plugins/terminalshot.py:21
@ -552,15 +561,15 @@ msgstr "Оставить терминал открытым"
#: ../terminatorlib/preferences.glade.h:11
msgid "Black on light yellow"
msgstr "Черный на светло-жёлтом"
msgstr "Чёрный на светло-жёлтом"
#: ../terminatorlib/preferences.glade.h:12
msgid "Black on white"
msgstr "Черный на белом"
msgstr "Чёрный на белом"
#: ../terminatorlib/preferences.glade.h:13
msgid "Gray on black"
msgstr "серый на чёрном"
msgstr "Серый на чёрном"
#: ../terminatorlib/preferences.glade.h:14
msgid "Green on black"
@ -572,7 +581,7 @@ msgstr "Белый на чёрном"
#: ../terminatorlib/preferences.glade.h:16
msgid "Orange on black"
msgstr "Оранжевый на черном"
msgstr "Оранжевый на чёрном"
#: ../terminatorlib/preferences.glade.h:17
msgid "Ambience"
@ -592,7 +601,7 @@ msgstr "Gruvbox светлая"
#: ../terminatorlib/preferences.glade.h:21
msgid "Gruvbox dark"
msgstr "Gruvbox темная"
msgstr "Gruvbox тёмная"
#: ../terminatorlib/preferences.glade.h:22
msgid "Custom"
@ -616,7 +625,7 @@ msgstr "Используемый в GNOME по умолчанию"
#: ../terminatorlib/preferences.glade.h:27
msgid "Click to focus"
msgstr "Активизация при щелчке мышью"
msgstr "Фокус по щелчку"
#: ../terminatorlib/preferences.glade.h:28
msgid "Follow mouse pointer"
@ -684,7 +693,7 @@ msgstr "Полноэкранный режим"
#: ../terminatorlib/preferences.glade.h:45
msgid "Terminator Preferences"
msgstr "Терминатор Параметры"
msgstr "Параметры Terminator"
#: ../terminatorlib/preferences.glade.h:46
msgid "<b>Behavior</b>"
@ -716,7 +725,7 @@ msgstr "Подсказка геометрии окна"
#: ../terminatorlib/preferences.glade.h:53
msgid "DBus server"
msgstr "DBus сервер"
msgstr "Сервер DBus"
#: ../terminatorlib/preferences.glade.h:54
msgid "Mouse focus:"
@ -728,11 +737,11 @@ msgstr "Режим трансляции нажатий клавиш"
#: ../terminatorlib/preferences.glade.h:56
msgid "PuTTY style paste:"
msgstr ""
msgstr "Стиль вставки PuTTY:"
#: ../terminatorlib/preferences.glade.h:57
msgid "Smart copy"
msgstr "\"Умное\" копирование"
msgstr "«Умное» копирование"
#: ../terminatorlib/preferences.glade.h:58
msgid "Re-use profiles for new terminals"
@ -744,23 +753,23 @@ msgstr "Использовать пользовательский обработ
#: ../terminatorlib/preferences.glade.h:60
msgid "PRIMARY"
msgstr ""
msgstr "PRIMARY"
#: ../terminatorlib/preferences.glade.h:61
msgid "Clipboard"
msgstr ""
msgstr "Буфер обмена"
#: ../terminatorlib/preferences.glade.h:62
msgid "Clear selection on copy"
msgstr ""
msgstr "Отменить выделение при копировании"
#: ../terminatorlib/preferences.glade.h:63
msgid "Open links with a single click (instead of Ctrl-left click)"
msgstr ""
msgstr "Открывать ссылки щелчком мыши (вместо Ctrl+ЛКМ)"
#: ../terminatorlib/preferences.glade.h:64
msgid "Disable mouse paste"
msgstr ""
msgstr "Отключить вставку мышью"
#: ../terminatorlib/preferences.glade.h:65
msgid "Custom URL handler:"
@ -788,11 +797,11 @@ msgstr "Дополнительные стили (зависит от темы)"
#: ../terminatorlib/preferences.glade.h:71
msgid "Cell Height:"
msgstr ""
msgstr "Высота ячейки:"
#: ../terminatorlib/preferences.glade.h:72
msgid "Cell Width:"
msgstr ""
msgstr "Ширина ячейки:"
#: ../terminatorlib/preferences.glade.h:73
msgid "Tab position:"
@ -808,7 +817,7 @@ msgstr "Кнопки переключения вкладок"
#: ../terminatorlib/preferences.glade.h:76
msgid "Title bar at bottom (Require restart)"
msgstr ""
msgstr "Панель заголовка внизу (требуется перезапуск)"
#: ../terminatorlib/preferences.glade.h:77
msgid "Global"
@ -844,11 +853,11 @@ msgstr "Копирование на выбор"
#: ../terminatorlib/preferences.glade.h:85
msgid "Disable Ctrl+mousewheel zoom"
msgstr ""
msgstr "Отключить масштабирование через Ctrl+колёсико мыши"
#: ../terminatorlib/preferences.glade.h:86
msgid "Select-by-_word characters:"
msgstr "Выбор _слов по символам:"
msgstr "Символы, выделяемые по _слову:"
#: ../terminatorlib/preferences.glade.h:87
msgid "<b>Cursor</b>"
@ -864,11 +873,11 @@ msgstr "Мерцание"
#: ../terminatorlib/preferences.glade.h:90
msgid "Use default colors"
msgstr ""
msgstr "Цвет по умолчанию"
#: ../terminatorlib/preferences.glade.h:91
msgid "Foreground:"
msgstr ""
msgstr "Передний план:"
#: ../terminatorlib/preferences.glade.h:92
msgid "Background:"
@ -928,11 +937,11 @@ msgstr "Встроенные с_хемы:"
#: ../terminatorlib/preferences.glade.h:107
msgid "_Foreground:"
msgstr ""
msgstr "ередний план"
#: ../terminatorlib/preferences.glade.h:108
msgid "_Background:"
msgstr ""
msgstr "_Задний план:"
#: ../terminatorlib/preferences.glade.h:109
msgid "<b>Palette</b>"
@ -948,7 +957,7 @@ msgstr "Цветовая _палитра:"
#: ../terminatorlib/preferences.glade.h:112
msgid "Show b_old text in bright colors"
msgstr ""
msgstr "Показывать п_олужирный текст в светлых цветах"
#: ../terminatorlib/preferences.glade.h:113
msgid "Colors"
@ -964,19 +973,19 @@ msgstr "_Прозрачный фон"
#: ../terminatorlib/preferences.glade.h:116
msgid "Background Image"
msgstr ""
msgstr "Фоновое изображение"
#: ../terminatorlib/preferences.glade.h:117
msgid "Background Image File:"
msgstr ""
msgstr "Файл фонового изображения"
#: ../terminatorlib/preferences.glade.h:118
msgid "Choose file"
msgstr ""
msgstr "Выберите файл"
#: ../terminatorlib/preferences.glade.h:119
msgid "S_hade background:"
msgstr ""
msgstr "З_атенение фона:"
#: ../terminatorlib/preferences.glade.h:120
msgid "<small><i>None</i></small>"
@ -1022,12 +1031,12 @@ msgstr "Прокрутка"
msgid ""
"<small><i><b>Note:</b> These options may cause some applications to behave "
"incorrectly. They are only here to allow you to work around certain "
"applications and operating systems that expect different terminal behavior.</"
"i></small>"
"applications and operating systems that expect different terminal "
"behavior.</i></small>"
msgstr ""
"<small><i><b>Замечание:</b> Эти параметры могут вызвать некорректную работу "
"некоторых приложений. Они представлены только для того, чтобы позволить "
"работать с некоторыми приложениями и операционными ситемами, ожидающими "
"работать с некоторыми приложениями и операционными системами, ожидающими "
"другого поведения терминала. </i></small>"
#: ../terminatorlib/preferences.glade.h:131
@ -1072,7 +1081,7 @@ msgstr "Укажите шрифт заголовка"
#: ../terminatorlib/preferences.glade.h:141
msgid "Titlebar"
msgstr ""
msgstr "Заголовок окна"
#: ../terminatorlib/preferences.glade.h:142
#: ../terminatorlib/terminal_popup_menu.py:204
@ -1113,11 +1122,11 @@ msgstr "Комбинации клавиш"
#: ../terminatorlib/preferences.glade.h:153
msgid "Plugin"
msgstr "Надстройка"
msgstr "Модуль"
#: ../terminatorlib/preferences.glade.h:154
msgid "This plugin has no configuration options"
msgstr "Этот плагин не имеет параметров конфигурации"
msgstr "Этот модуль не имеет параметров конфигурации"
#: ../terminatorlib/preferences.glade.h:155
msgid "Plugins"
@ -1125,32 +1134,17 @@ msgstr "Модули"
#: ../terminatorlib/preferences.glade.h:158
msgid "Version: 2.1.1"
msgstr ""
msgstr "Версия: 2.1.1"
#: ../terminatorlib/preferences.glade.h:159
msgid ""
"The goal of this project is to produce a useful tool for arranging "
"terminals. It is inspired by programs such as gnome-multi-term, quadkonsole, "
"etc. in that the main focus is arranging terminals in grids (tabs is the "
"most common default method, which Terminator also supports).\n"
"The goal of this project is to produce a useful tool for arranging terminals. It is inspired by programs such as gnome-multi-term, quadkonsole, etc. in that the main focus is arranging terminals in grids (tabs is the most common default method, which Terminator also supports).\n"
"\n"
"Much of the behavior of Terminator is based on GNOME Terminal, and we are "
"adding more features from that as time goes by, but we also want to extend "
"out in different directions with useful features for sysadmins and other "
"users. If you have any suggestions, please file wishlist bugs! (see left for "
"the Development link)"
"Much of the behavior of Terminator is based on GNOME Terminal, and we are adding more features from that as time goes by, but we also want to extend out in different directions with useful features for sysadmins and other users. If you have any suggestions, please file wishlist bugs! (see left for the Development link)"
msgstr ""
"Задачей данного проекта является создание удобного инструмента для "
"совмещения терминалов. Вдохновленный такими программами как gnome-multi-"
"term, quadkonsole и подобных, он прежде всего нацелен собирать терминалы в "
"сетки (которые в свою очередь могут разноситься по вкладкам, которые, кстати "
"Terminator так же поддерживает).\n"
"Задачей данного проекта является создание удобного инструмента для совмещения терминалов. Вдохновлённый такими программами как gnome-multi-term, quadkonsole и подобных, он прежде всего нацелен собирать терминалы в сетки (которые в свою очередь могут разноситься по вкладкам, которые, кстати Terminator так же поддерживает).\n"
"\n"
"Большая часть функционала заимствована из GNOME Terminal и мы со временем "
"добавляем больше разных плюшек оттуда. Но хотелось бы как-то еще расширить "
"его возможности для сисадминов и прочих пользователей. Если у вас есть какие-"
"либо предложения, пожалуйста озвучьте их на багтрекере (wishlist bugs)! (см. "
"сайт разработчиков)"
"Большая часть функционала заимствована из GNOME Terminal и мы со временем добавляем больше разных плюшек оттуда. Но хотелось бы как-то еще расширить его возможности для сисадминов и прочих пользователей. Если у вас есть какие-либо предложения, пожалуйста озвучьте их на багтрекере (wishlist bugs)! (см. сайт разработчиков)"
#: ../terminatorlib/preferences.glade.h:162
msgid "The Manual"
@ -1159,9 +1153,10 @@ msgstr "Руководство"
#: ../terminatorlib/preferences.glade.h:163
msgid ""
"<a href=\"https://github.com/gnome-terminator/terminator\">Development</a>\n"
"<a href=\"https://github.com/gnome-terminator/terminator/issues\">Bugs / "
"Enhancements</a>"
"<a href=\"https://github.com/gnome-terminator/terminator/issues\">Bugs / Enhancements</a>"
msgstr ""
"<a href=\"https://github.com/gnome-terminator/terminator\">Разработка</a>\n"
"<a href=\"https://github.com/gnome-terminator/terminator/issues\">Ошибки / Улучшения</a>"
#: ../terminatorlib/preferences.glade.h:165
msgid "About"
@ -1181,15 +1176,15 @@ msgstr "Восстановить размер шрифта"
#: ../terminatorlib/prefseditor.py:107
msgid "Increase font size on all terminals"
msgstr ""
msgstr "Увеличить размер шрифта во всех терминалах"
#: ../terminatorlib/prefseditor.py:108
msgid "Decrease font size on all terminals"
msgstr ""
msgstr "Уменьшить размер шрифта во всех терминалах"
#: ../terminatorlib/prefseditor.py:109
msgid "Restore original font size on all terminals"
msgstr ""
msgstr "Восстановить исходный размер шрифта во всех терминалах"
#: ../terminatorlib/prefseditor.py:110
msgid "Create a new tab"
@ -1249,7 +1244,7 @@ msgstr "Вставить из буфера обмена"
#: ../terminatorlib/prefseditor.py:126
msgid "Paste primary selection"
msgstr ""
msgstr "Вставить первоначальный выделенный фрагмент"
#: ../terminatorlib/prefseditor.py:127
msgid "Show/Hide the scrollbar"
@ -1385,7 +1380,7 @@ msgstr "Показать/Скрыть окно"
#: ../terminatorlib/prefseditor.py:160
msgid "Create new group"
msgstr ""
msgstr "Создать новую группу"
#: ../terminatorlib/prefseditor.py:161
msgid "Group all terminals"
@ -1393,7 +1388,7 @@ msgstr "Группировать все терминалы"
#: ../terminatorlib/prefseditor.py:162
msgid "Group/Ungroup all terminals"
msgstr "Группировать/разрознить все терминалы"
msgstr "Группировать/разделить все терминалы"
#: ../terminatorlib/prefseditor.py:163
msgid "Ungroup all terminals"
@ -1401,15 +1396,15 @@ msgstr "Разгруппировать все терминалы"
#: ../terminatorlib/prefseditor.py:164
msgid "Group terminals in window"
msgstr ""
msgstr "Группировать терминалы в окне"
#: ../terminatorlib/prefseditor.py:165
msgid "Group/Ungroup terminals in window"
msgstr ""
msgstr "Группировать/разделить терминалы в окне"
#: ../terminatorlib/prefseditor.py:166
msgid "Ungroup terminals in window"
msgstr ""
msgstr "Разгруппировать терминалы в окне"
#: ../terminatorlib/prefseditor.py:167
msgid "Group terminals in tab"
@ -1417,7 +1412,7 @@ msgstr "Группировать терминалы во вкладке"
#: ../terminatorlib/prefseditor.py:168
msgid "Group/Ungroup terminals in tab"
msgstr "Группировать/разрознить терминалы во вкладке"
msgstr "Группировать/разделить терминалы во вкладке"
#: ../terminatorlib/prefseditor.py:169
msgid "Ungroup terminals in tab"
@ -1429,7 +1424,7 @@ msgstr "Создать новое окно"
#: ../terminatorlib/prefseditor.py:171
msgid "Spawn a new Terminator process"
msgstr "Создать новый процесс Terminator'а"
msgstr "Создать новый процесс Terminator"
#: ../terminatorlib/prefseditor.py:172
msgid "Don't broadcast key presses"
@ -1449,7 +1444,7 @@ msgstr "Вставить номер терминала"
#: ../terminatorlib/prefseditor.py:176
msgid "Insert padded terminal number"
msgstr "Вставить номер терминала"
msgstr "Вставить дополненный номер терминала"
#: ../terminatorlib/prefseditor.py:177
msgid "Edit window title"
@ -1477,17 +1472,17 @@ msgstr "Переключиться на предыдущий профиль"
#: ../terminatorlib/prefseditor.py:183
msgid "Open the Preferences window"
msgstr ""
msgstr "Открыть окно параметров"
#: ../terminatorlib/prefseditor.py:184
msgid "Open the manual"
msgstr "Открыть руководство"
#: ../terminatorlib/prefseditor.py:1370
#: ../terminatorlib/prefseditor.py:1366
msgid "New Profile"
msgstr "Создать профиль"
#: ../terminatorlib/prefseditor.py:1413 ../terminatorlib/prefseditor.py:1418
#: ../terminatorlib/prefseditor.py:1409 ../terminatorlib/prefseditor.py:1414
msgid "New Layout"
msgstr "Новое расположение"
@ -1534,7 +1529,7 @@ msgstr "Вст_авить"
#: ../terminatorlib/terminal_popup_menu.py:112
msgid "Set W_indow Title"
msgstr ""
msgstr "Указать название о_кна"
#: ../terminatorlib/terminal_popup_menu.py:117
msgid "Split H_orizontally"
@ -1574,7 +1569,7 @@ msgstr "Группирование"
#: ../terminatorlib/terminal_popup_menu.py:186
msgid "Relaunch Command"
msgstr ""
msgstr "Перезапустить команду"
#: ../terminatorlib/terminal_popup_menu.py:191
msgid "Show _scrollbar"
@ -1582,7 +1577,7 @@ msgstr "Показать полосу прокрутки"
#: ../terminatorlib/terminal_popup_menu.py:248
msgid "_Layouts..."
msgstr ""
msgstr "аблоны..."
#: ../terminatorlib/terminal.py:481
msgid "N_ew group..."
@ -1599,11 +1594,11 @@ msgstr "Удалить группу %s"
#: ../terminatorlib/terminal.py:512
msgid "G_roup all in window"
msgstr ""
msgstr "С_группировать всё в окне"
#: ../terminatorlib/terminal.py:517
msgid "Ungro_up all in window"
msgstr ""
msgstr "Раз_группировать всё в окне"
#: ../terminatorlib/terminal.py:522
msgid "G_roup all in tab"
@ -1611,7 +1606,7 @@ msgstr "С_группировать всё во вкладке"
#: ../terminatorlib/terminal.py:527
msgid "Ungro_up all in tab"
msgstr "Раз_рознить терминалы во вкладке"
msgstr "Раз_группировать терминалы во вкладке"
#: ../terminatorlib/terminal.py:532
msgid "Remove all groups"
@ -1650,25 +1645,25 @@ msgstr "_Добавить номер терминала"
msgid "Insert _padded terminal number"
msgstr "Вставить _номер терминала"
#: ../terminatorlib/terminal.py:1490
#: ../terminatorlib/terminal.py:1492
msgid "Unable to find a shell"
msgstr "Не удается найти оболочку (shell)"
#: ../terminatorlib/terminal.py:1521
#: ../terminatorlib/terminal.py:1546
msgid "Unable to start shell:"
msgstr "Не удается запустить оболочку:"
#: ../terminatorlib/terminal.py:1975
#: ../terminatorlib/terminal.py:2000
msgid "Rename Window"
msgstr "Переименование окна"
#: ../terminatorlib/terminal.py:1983
#: ../terminatorlib/terminal.py:2008
msgid "Enter a new title for the Terminator window..."
msgstr "Введите новое название для окна Terminator..."
#: ../terminatorlib/titlebar.py:112
msgid "[INACTIVE: Right-Click for Relaunch option] "
msgstr ""
msgstr "[НЕАКТИВНО: Щёлкните правой кнопкой мыши для функции перезапуска] "
#: ../terminatorlib/titlebar.py:258
msgid "Alpha"
@ -1773,117 +1768,9 @@ msgstr "окно"
#: ../terminatorlib/window.py:773
#, python-format
msgid "Window group %s"
msgstr ""
msgstr "Группа окон %s"
#: ../terminatorlib/window.py:799
#, python-format
msgid "Tab %d"
msgstr "Вкладка %d"
#~ msgid "Current Locale"
#~ msgstr "Текущая языковая настройка"
#~ msgid "Western"
#~ msgstr "Западная"
#~ msgid "Central European"
#~ msgstr "Центрально-европейская"
#~ msgid "South European"
#~ msgstr "Южно-европейская"
#~ msgid "Baltic"
#~ msgstr "Балтийская"
#~ msgid "Cyrillic"
#~ msgstr "Кириллица"
#~ msgid "Arabic"
#~ msgstr "Арабская"
#~ msgid "Greek"
#~ msgstr "Греческая"
#~ msgid "Hebrew Visual"
#~ msgstr "Иврит (Визуальный)"
#~ msgid "Hebrew"
#~ msgstr "Иврит"
#~ msgid "Turkish"
#~ msgstr "Турецкая"
#~ msgid "Nordic"
#~ msgstr "Скандинавская"
#~ msgid "Celtic"
#~ msgstr "Кельтская"
#~ msgid "Romanian"
#~ msgstr "Румынская"
#~ msgid "Unicode"
#~ msgstr "Юникод"
#~ msgid "Armenian"
#~ msgstr "Армянская"
#~ msgid "Chinese Traditional"
#~ msgstr "Традиционная китайская"
#~ msgid "Cyrillic/Russian"
#~ msgstr "Кириллица/Русская"
#~ msgid "Japanese"
#~ msgstr "Японская"
#~ msgid "Korean"
#~ msgstr "Корейская"
#~ msgid "Chinese Simplified"
#~ msgstr "Упрощенная китайская"
#~ msgid "Georgian"
#~ msgstr "Грузинская"
#~ msgid "Cyrillic/Ukrainian"
#~ msgstr "Кириллица/Украина"
#~ msgid "Croatian"
#~ msgstr "Хорватская"
#~ msgid "Hindi"
#~ msgstr "Хинди"
#~ msgid "Persian"
#~ msgstr "Персидская"
#~ msgid "Gujarati"
#~ msgstr "Гуарати (Индия)"
#~ msgid "Gurmukhi"
#~ msgstr "Гармукхи"
#~ msgid "Icelandic"
#~ msgstr "Исладнский"
#~ msgid "Vietnamese"
#~ msgstr "Вьетнамский"
#~ msgid "Thai"
#~ msgstr "Тайский"
#~ msgid "Encoding:"
#~ msgstr "Кодировка:"
#~ msgid "Encodings"
#~ msgstr "Кодировки"
#~ msgid "Default"
#~ msgstr "По умолчанию"
#~ msgid "User defined"
#~ msgstr "Пользовательский"
#~ msgid "Other Encodings"
#~ msgstr "Другие кодировки"

View File

@ -175,7 +175,7 @@ class InstallData(install_data):
return data_files
if platform.system() in ['FreeBSD', 'OpenBSD']:
if platform.system() in ['OpenBSD']:
man_dir = 'man'
else:
man_dir = 'share/man'
@ -219,9 +219,6 @@ setup(name=APP_NAME,
'terminatorlib',
'terminatorlib.plugins',
],
setup_requires=[
'pytest-runner',
],
install_requires=[
'pycairo',
'configobj',
@ -229,7 +226,6 @@ setup(name=APP_NAME,
'pygobject',
'psutil',
],
tests_require=test_deps,
extras_require={'test': test_deps},
package_data={'terminatorlib': ['preferences.glade', 'layoutlauncher.glade']},
cmdclass={'build': BuildData, 'install_data': InstallData, 'uninstall': Uninstall},

View File

@ -21,8 +21,7 @@
import sys
import os
import psutil
import pwd
try:
ORIGCWD = os.getcwd()
except OSError:
@ -111,11 +110,9 @@ if __name__ == '__main__':
elif OPTIONS.toggle_visibility:
dbg('requesting to toggle windows visibility')
ipc.toggle_visibility_cmdline(optionslist)
if OPTIONS.reload:
elif OPTIONS.reload:
dbg('requesting to reload configuration for all windows')
ipc.reload_configuration()
elif OPTIONS.unhide:
print('requesting to unhide windows')
ipc.unhide_cmdline(optionslist)

View File

@ -105,7 +105,7 @@ DEFAULTS = {
'enabled_plugins' : ['LaunchpadBugURLHandler',
'LaunchpadCodeURLHandler',
'APTURLHandler'],
'suppress_multiple_term_dialog': False,
'ask_before_closing' : 'multiple_terminals',
'always_split_with_profile': False,
'putty_paste_style' : False,
'putty_paste_style_source_clipboard': False,
@ -499,6 +499,34 @@ class Config(object):
"""Set a layout"""
return(self.base.set_layout(layout, tree))
def copy_layout_item(self, src_layout, dst_layout, item):
items = {}
for child in src_layout:
section = src_layout[child]
sec_type = section.get('type', None)
if sec_type != 'Terminal':
continue
cp_item = section.get(item, None)
uuid = str(section.get('uuid', None))
if cp_item:
items[uuid] = cp_item
dbg("items to be copied:%s" % items)
for child in dst_layout:
section = dst_layout[child]
sec_type = section.get('type', None)
if sec_type != 'Terminal':
continue
uuid = str(section.get('uuid', None))
update_item = items.get(uuid, None)
if uuid and update_item:
dbg("update layout item:(%s) with value:(%s)"
% (item, update_item))
section[item] = update_item
class ConfigBase(Borg):
"""Class to provide access to our user configuration"""
loaded = None
@ -622,12 +650,7 @@ class ConfigBase(Borg):
dbg('config already loaded')
return
if self.command_line_options and self.command_line_options.config:
filename = self.command_line_options.config
else:
filename = os.path.join(get_config_dir(), 'config')
if not os.path.exists(filename):
filename = os.path.join(get_system_config_dir(), 'config')
filename = self.get_config_filename()
dbg('looking for config file: %s' % filename)
try:
#
@ -706,6 +729,68 @@ class ConfigBase(Borg):
self.loaded = True
def get_config_filename(self):
filename = ''
if self.command_line_options and self.command_line_options.config:
filename = self.command_line_options.config
else:
filename = os.path.join(get_config_dir(), 'config')
if not os.path.exists(filename):
filename = os.path.join(get_system_config_dir(), 'config')
return filename
def save_config_with_suffix(self, suffix):
try:
filename = self.get_config_filename()
#save the current config, to revert any changes make in preferences
#save the current config to config_dir path which is at least writable
cfg_filename = os.path.join(get_config_dir(), 'config')
cur_loaded_file = cfg_filename + suffix
if os.path.exists(filename) and cur_loaded_file:
dbg('copy file:%s to' \
' file:%s' % (filename, cur_loaded_file))
shutil.copy2(filename, cur_loaded_file)
elif cur_loaded_file:
open(cur_loaded_file, 'a').close()
else:
err('ConfigBase:: Unable to get filename to save')
except Exception as ex:
err('ConfigBase::save_config_with_suffix' \
' Unable to save config: %s' % ex)
def restore_config_with_suffix(self, suffix):
try:
filename = self.get_config_filename()
cfg_filename = os.path.join(get_config_dir(), 'config')
cur_loaded_file = cfg_filename + suffix
if os.path.exists(cur_loaded_file):
if not os.access(filename, os.W_OK):
dbg('path:%s not writable' \
' restoring to path:%s' % (filename,cfg_filename))
filename = cfg_filename
dbg('restore from file:%s to file:%s'
% (cur_loaded_file, filename))
shutil.copy2(cur_loaded_file, filename)
except Exception as ex:
err('ConfigBase::restore_config_with_suffix' \
' Unable to restore config: %s' % ex)
def remove_config_with_suffix(self, suffix):
try:
cfg_filename = os.path.join(get_config_dir(), 'config')
cur_loaded_file = cfg_filename + suffix
if os.path.exists(cur_loaded_file):
dbg('remove file:%s' % (cur_loaded_file))
os.remove(cur_loaded_file)
except Exception as ex:
err('ConfigBase::remove_config_with_suffix' \
' Unable to remove config: %s' % ex)
def reload(self):
"""Force a reload of the base config"""
self.loaded = False
@ -771,7 +856,8 @@ class ConfigBase(Borg):
open(filename, 'a').close()
backup_file = filename + '~'
shutil.copy2(filename, backup_file)
if os.path.exists(filename):
shutil.copy2(filename, backup_file)
with open(filename, 'wb') as fh:
parser.write(fh)

View File

@ -152,33 +152,54 @@ class Container(object):
"""Unzoom a terminal"""
raise NotImplementedError('unzoom')
def construct_confirm_close(self, window, reqtype):
def construct_confirm_close(self, window, child):
"""Create a confirmation dialog for closing things"""
maker = Factory()
has_multiple_terms = False
if not maker.isinstance(child, 'Terminal'):
has_multiple_terms = True
elif maker.isinstance(self, 'Window'):
has_multiple_terms = self.is_zoomed()
# skip this dialog if applicable
if self.config['suppress_multiple_term_dialog']:
if self.config['ask_before_closing'] == 'never':
return Gtk.ResponseType.ACCEPT
elif self.config['ask_before_closing'] == 'multiple_terminals':
if not has_multiple_terms:
return Gtk.ResponseType.ACCEPT
# text
confirm_button_text = (_('Close _Terminals') if has_multiple_terms
else _('Close _Terminal'))
big_label_text = (_('Close multiple terminals?') if has_multiple_terms
else _('Close terminal?'))
if not has_multiple_terms:
description_text = _('Do you really wish to close this terminal?')
elif maker.isinstance(self, 'Window'):
description_text = _('This window has several terminals open. Closing \
the window will also close all terminals within it.')
elif maker.isinstance(self, 'Notebook'):
description_text = _('This tab has several terminals open. Closing \
the tab will also close all terminals within it.')
else:
description_text = ''
# dialog GUI
dialog = Gtk.Dialog(_('Close?'), window, Gtk.DialogFlags.MODAL)
dialog.set_resizable(False)
dialog.add_button(Gtk.STOCK_CANCEL, Gtk.ResponseType.REJECT)
c_all = dialog.add_button(Gtk.STOCK_CLOSE, Gtk.ResponseType.ACCEPT)
c_all.get_children()[0].get_children()[0].get_children()[1].set_label(
_('Close _Terminals'))
confirm_button_text)
primary = Gtk.Label(label=_('<big><b>Close multiple terminals?</b></big>'))
primary = Gtk.Label(label=_('<big><b>' + big_label_text + '</b></big>'))
primary.set_use_markup(True)
primary.set_alignment(0, 0.5)
if reqtype == 'window':
label_text = _('This window has several terminals open. Closing \
the window will also close all terminals within it.')
elif reqtype == 'tab':
label_text = _('This tab has several terminals open. Closing \
the tab will also close all terminals within it.')
else:
label_text = ''
secondary = Gtk.Label(label=label_text)
secondary = Gtk.Label(label=description_text)
secondary.set_line_wrap(True)
labels = Gtk.VBox()
@ -203,7 +224,8 @@ the tab will also close all terminals within it.')
# set configuration
self.config.base.reload()
self.config['suppress_multiple_term_dialog'] = checkbox.get_active()
if checkbox.get_active():
self.config['ask_before_closing'] = 'never'
self.config.save()
dialog.destroy()

View File

@ -359,6 +359,7 @@ def new_tab_cmdline(session, options):
def toggle_visibility_cmdline(session,options):
session.toggle_visibility_cmdline(options)
@with_proxy
def reload_configuration(session):
"""Call the dbus method to reload configuration for all windows"""
session.reload_configuration()

View File

@ -343,10 +343,6 @@ class Notebook(Container, Gtk.Notebook):
self.set_current_page(tabpos)
self.show_all()
if maker.isinstance(term_widget, 'Terminal'):
#notify plugins of tab-change
dbg("emit tab-change for tabpos: %s " % tabpos)
term_widget.emit('tab-change', tabpos)
self.set_current_page(tabpos)
widget.grab_focus()
def wrapcloseterm(self, widget):
@ -379,35 +375,33 @@ class Notebook(Container, Gtk.Notebook):
maker = Factory()
child = nb.get_nth_page(tabnum)
confirm_close = self.construct_confirm_close(self.window, child)
if confirm_close != Gtk.ResponseType.ACCEPT:
dbg('user cancelled request')
return
if maker.isinstance(child, 'Terminal'):
dbg('child is a single Terminal')
del nb.last_active_term[child]
child.close()
# FIXME: We only do this del and return here to avoid removing the
# page below, which child.close() implicitly does
del(label)
return
elif maker.isinstance(child, 'Container'):
dbg('child is a Container')
result = self.construct_confirm_close(self.window, _('tab'))
if result == Gtk.ResponseType.ACCEPT:
containers = None
objects = None
containers, objects = enumerate_descendants(child)
containers = None
objects = None
containers, objects = enumerate_descendants(child)
while len(objects) > 0:
descendant = objects.pop()
descendant.close()
while Gtk.events_pending():
Gtk.main_iteration()
return
else:
dbg('user cancelled request')
return
while len(objects) > 0:
descendant = objects.pop()
descendant.close()
while Gtk.events_pending():
Gtk.main_iteration()
else:
err('Notebook::closetab: child is unknown type %s' % child)
return
def resizeterm(self, widget, keyname):
"""Handle a keyboard event requesting a terminal resize"""

View File

@ -16,6 +16,7 @@
"""Terminator.optionparse - Parse commandline options"""
import argparse
from argparse import RawTextHelpFormatter
import sys
import os
@ -37,7 +38,7 @@ def parse_options():
"""Parse the command line options"""
is_x_terminal_emulator = os.path.basename(sys.argv[0]) == 'x-terminal-emulator'
parser = argparse.ArgumentParser()
parser = argparse.ArgumentParser(formatter_class=RawTextHelpFormatter)
parser.add_argument('-R', '--reload', action='store_true', dest='reload',
help=_('Reload terminator configuration'))
@ -59,6 +60,16 @@ def parse_options():
parser.add_argument('--geometry', dest='geometry', type=str,
help=_('Set the preferred size and position of the window'
'(see X man page)'))
parser.add_argument('--guake-key', dest='guake_key', type=str,
help=_('A Guake like terminal mode where terminal can be toggled by a key.\nUsage Example: terminator --guake-key="F8" --guake-side left --guake-width 700 --guake-height 800'))
parser.add_argument('--guake-side', dest='guake_side', default="top", type=str,
help=_('Set the preferred screen edge position of a terminal in Guake like mode.\nOptions: top, bottom, left, right\nDefault: top'))
parser.add_argument('--guake-width', dest='guake_width', default="800", type=str,
help=_('Set the preferred width when using Guake like mode. Default: 800'
'(see X man page)'))
parser.add_argument('--guake-height', dest='guake_height', default="600", type=str,
help=_('Set the preferred height when using Guake like mode. Default: 600'
'(see X man page)'))
if not is_x_terminal_emulator:
parser.add_argument('-e', '--command', dest='command',
help=_('Specify a command to execute inside the terminal'))

View File

@ -1,8 +1,15 @@
# Terminator by Chris Jones <cmsj@tenshu.net>
# GPL v2 only
#
# -added keybinding, bookmark functionality
# -made name parsing to menu, optional
# - Vishweshwar Saran Singh Deo vssdeo@gmail.com
# TODO: tags
"""custom_commands.py - Terminator Plugin to add custom command menu entries"""
import sys
import os
import time
# Fix imports when testing this file directly
if __name__ == '__main__':
@ -14,8 +21,17 @@ import terminatorlib.plugin as plugin
from terminatorlib.config import Config
from terminatorlib.translation import _
from terminatorlib.util import get_config_dir, err, dbg, gerr
from terminatorlib.terminator import Terminator
(CC_COL_ENABLED, CC_COL_NAME, CC_COL_COMMAND) = list(range(0,3))
from terminatorlib.plugin import KeyBindUtil
(CC_COL_ENABLED, CC_COL_NAME, CC_COL_NAME_PARSE, CC_COL_COMMAND) = list(range(0,4))
PluginActAdd = "plugin_add"
PluginActBmk = "plugin_bmk"
PluginAddDesc = "Plugin Add Bookmark"
PluginBmkDesc = "Plugin Open Bookmark Preferences"
# Every plugin you want Terminator to load *must* be listed in 'AVAILABLE'
AVAILABLE = ['CustomCommandsMenu']
@ -25,10 +41,27 @@ class CustomCommandsMenu(plugin.MenuItem):
capabilities = ['terminal_menu']
cmd_list = {}
conf_file = os.path.join(get_config_dir(),"custom_commands")
keyb = None
def __init__( self):
# In prev code dbox is needed if _create_command_dialog func is called
# after configure func where dbox is init. In case we call
# _create_command_dialog without calling configure func, like in quick
# bookmark add then we need to check.
self.dbox = None
config = Config()
sections = config.plugin_get_config(self.__class__.__name__)
self.connect_signals()
self.keyb = KeyBindUtil(config)
self.keyb.bindkey_check_config(
[PluginAddDesc , PluginActAdd, "<Alt>b"])
self.keyb.bindkey_check_config(
[PluginBmkDesc , PluginActBmk, "<Shift><Alt>b"])
if not isinstance(sections, dict):
return
noord_cmds = []
@ -38,24 +71,110 @@ class CustomCommandsMenu(plugin.MenuItem):
print("CustomCommandsMenu: Ignoring section %s" % s)
continue
name = s["name"]
name_parse = s.get("name_parse", "True")
command = s["command"]
enabled = s["enabled"] and s["enabled"] or False
if "position" in s:
self.cmd_list[int(s["position"])] = {'enabled' : enabled,
'name' : name,
'name_parse' : name_parse,
'command' : command
}
else:
noord_cmds.append(
{'enabled' : enabled,
'name' : name,
'name_parse' : name_parse,
'command' : command
}
)
for cmd in noord_cmds:
self.cmd_list[len(self.cmd_list)] = cmd
def unload(self):
dbg("unloading")
for window in self.windows:
try:
window.disconnect_by_func(self.on_keypress)
except:
dbg("no connected signals")
self.keyb.unbindkey(
[PluginAddDesc , PluginActAdd, "<Alt>b"])
self.keyb.unbindkey(
[PluginBmkDesc , PluginActBmk, "<Shift><Alt>b"])
def connect_signals(self):
self.windows = Terminator().get_windows()
for window in self.windows:
window.connect('key-press-event', self.on_keypress)
def get_last_exe_cmd(self):
cur_win = Terminator().last_focused_term.get_toplevel()
#TODO: there has to be a better way to get the last command executed
focus_term = cur_win.get_focussed_terminal()
tmp_file = os.path.join(os.sep, 'tmp', 'term_cmd')
command = 'fc -n -l -1 -1 > ' + tmp_file + '; #bookmark last cmd\n'
focus_term.vte.feed_child(str(command).encode("utf-8"))
fsz = 0
count = 0
while not (count == 2 or fsz):
time.sleep(0.1)
if os.path.exists(tmp_file):
fsz = os.path.getsize(tmp_file)
count += 1
last_cmd = None
try:
with open(tmp_file, 'r') as file:
last_cmd = file.read()
file.close()
except Exception as ex:
err('Unable to open %s ex: (%s)' % (tmp_file, ex))
if os.path.exists(tmp_file):
os.remove(tmp_file)
if last_cmd:
last_cmd = last_cmd.rstrip()
dbg('last exec cmd: (%s)' % last_cmd)
return last_cmd
def get_last_exe_cmd_dialog_vars(self):
last_exe_cmd = self.get_last_exe_cmd()
dialog_vars = { 'enabled' : True,
'name' : last_exe_cmd,
'name_parse': False,
'command' : last_exe_cmd }
return dialog_vars
def on_keypress(self, widget, event):
act = self.keyb.keyaction(event)
dbg("keyaction: (%s) (%s)" % (str(act), event.keyval))
if act == PluginActAdd:
dbg("add bookmark")
self.setup_store()
dialog_vars = self.get_last_exe_cmd_dialog_vars()
self.on_new(None, {'dialog_vars' : dialog_vars })
self.update_cmd_list(self.store)
self._save_config()
return True
if act == PluginActBmk:
dbg("open custom command preferences")
self.configure(None)
return True
def callback(self, menuitems, menu, terminal):
"""Add our menu items to the menu"""
submenus = {}
item = Gtk.MenuItem.new_with_mnemonic(_('_Custom Commands'))
@ -81,16 +200,20 @@ class CustomCommandsMenu(plugin.MenuItem):
branch_names = command['name'].split('/')[:-1]
target_submenu = submenu
parent_submenu = submenu
for idx in range(len(branch_names)):
lookup_name = '/'.join(branch_names[0:idx+1])
target_submenu = submenus.get(lookup_name, None)
if not target_submenu:
item = Gtk.MenuItem(_(branch_names[idx]))
parent_submenu.append(item)
target_submenu = Gtk.Menu()
item.set_submenu(target_submenu)
submenus[lookup_name] = target_submenu
parent_submenu = target_submenu
if not command['name_parse']:
leaf_name = command['name']
branch_names = ''
else:
for idx in range(len(branch_names)):
lookup_name = '/'.join(branch_names[0:idx+1])
target_submenu = submenus.get(lookup_name, None)
if not target_submenu:
item = Gtk.MenuItem(_(branch_names[idx]))
parent_submenu.append(item)
target_submenu = Gtk.Menu()
item.set_submenu(target_submenu)
submenus[lookup_name] = target_submenu
parent_submenu = target_submenu
if iconinfo:
image = Gtk.Image()
image.set_from_icon_name(exe, Gtk.IconSize.MENU)
@ -109,11 +232,13 @@ class CustomCommandsMenu(plugin.MenuItem):
for command in [ self.cmd_list[key] for key in sorted(self.cmd_list.keys()) ] :
enabled = command['enabled']
name = command['name']
name_parse = command['name_parse']
command = command['command']
item = {}
item['enabled'] = enabled
item['name'] = name
item['name_parse'] = name_parse
item['command'] = command
item['position'] = i
@ -128,6 +253,13 @@ class CustomCommandsMenu(plugin.MenuItem):
for terminal in data['terminals']:
terminal.vte.feed_child(command.encode())
def setup_store(self):
self.store = Gtk.ListStore(bool, str, bool, str)
for command in [ self.cmd_list[key] for key in sorted(self.cmd_list.keys()) ]:
self.store.append([command['enabled'], command['name'],
command['name_parse'], command['command']])
return self.store
def configure(self, widget, data = None):
ui = {}
dbox = Gtk.Dialog(
@ -139,7 +271,8 @@ class CustomCommandsMenu(plugin.MenuItem):
_("_OK"), Gtk.ResponseType.ACCEPT
)
)
dbox.set_transient_for(widget.get_toplevel())
if widget:
dbox.set_transient_for(widget.get_toplevel())
icon_theme = Gtk.IconTheme.get_default()
if icon_theme.lookup_icon('terminator-custom-commands', 48, 0):
@ -149,11 +282,8 @@ class CustomCommandsMenu(plugin.MenuItem):
icon = dbox.render_icon(Gtk.STOCK_DIALOG_INFO, Gtk.IconSize.BUTTON)
dbox.set_icon(icon)
store = Gtk.ListStore(bool, str, str)
store = self.setup_store()
for command in [ self.cmd_list[key] for key in sorted(self.cmd_list.keys()) ]:
store.append([command['enabled'], command['name'], command['command']])
treeview = Gtk.TreeView(store)
#treeview.connect("cursor-changed", self.on_cursor_changed, ui)
selection = treeview.get_selection()
@ -226,7 +356,10 @@ class CustomCommandsMenu(plugin.MenuItem):
button.set_sensitive(False)
ui['button_delete'] = button
button = Gtk.Button(_("Bookmark Last Cmd"))
button_box.pack_start(button, False, True, 0)
button.connect("clicked", self.on_last_exe_cmd, ui)
ui['button_save_last_cmd'] = button
hbox.pack_start(button_box, False, True, 0)
self.dbox = dbox
@ -237,6 +370,7 @@ class CustomCommandsMenu(plugin.MenuItem):
self._save_config()
del(self.dbox)
dbox.destroy()
self.dbox = None
return
@ -245,12 +379,14 @@ class CustomCommandsMenu(plugin.MenuItem):
self.cmd_list = {}
i=0
while iter:
(enabled, name, command) = store.get(iter,
(enabled, name, name_parse, command) = store.get(iter,
CC_COL_ENABLED,
CC_COL_NAME,
CC_COL_NAME_PARSE,
CC_COL_COMMAND)
self.cmd_list[i] = {'enabled' : enabled,
'name': name,
'name_parse' : name_parse,
'command' : command}
iter = store.iter_next(iter)
i = i + 1
@ -278,7 +414,8 @@ class CustomCommandsMenu(plugin.MenuItem):
data['button_edit'].set_sensitive(iter is not None)
data['button_delete'].set_sensitive(iter is not None)
def _create_command_dialog(self, enabled_var = False, name_var = "", command_var = ""):
def _create_command_dialog(self, enabled_var = False, name_var = "",
name_parse_var = "", command_var = ""):
dialog = Gtk.Dialog(
_("New Command"),
None,
@ -288,38 +425,85 @@ class CustomCommandsMenu(plugin.MenuItem):
_("_OK"), Gtk.ResponseType.ACCEPT
)
)
dialog.set_transient_for(self.dbox)
table = Gtk.Table(3, 2)
#since we call this via shortcut keybinding
#lets focus on OK button
buttonbox = dialog.get_action_area()
buttons = buttonbox.get_children()
dialog.set_focus(buttons[1])
# dbox is init in configure function, in case we want to
# create dialog directly
if self.dbox:
dialog.set_transient_for(self.dbox)
table = Gtk.Table(4, 2)
table.set_row_spacings(5)
table.set_col_spacings(5)
label = Gtk.Label(label=_("Enabled:"))
label.set_alignment(0, 0)
table.attach(label, 0, 1, 0, 1)
enabled = Gtk.CheckButton()
enabled.set_active(enabled_var)
table.attach(enabled, 1, 2, 0, 1)
label = Gtk.Label(label=_("Name:"))
label = Gtk.Label(label=_("Parse Name into SubMenu's:"))
label.set_alignment(0, 0)
table.attach(label, 0, 1, 1, 2)
name_parse = Gtk.CheckButton()
name_parse.set_active(name_parse_var)
table.attach(name_parse, 1, 2, 1, 2)
label = Gtk.Label(label=_("Name:"))
table.attach(label, 0, 1, 2, 3)
name = Gtk.Entry()
name.set_text(name_var)
table.attach(name, 1, 2, 1, 2)
table.attach(name, 1, 2, 2, 3)
label = Gtk.Label(label=_("Command:"))
table.attach(label, 0, 1, 2, 3)
table.attach(label, 0, 1, 3, 4)
command = Gtk.TextView()
command.get_buffer().set_text(command_var)
table.attach(command, 1, 2, 2, 3)
table.attach(command, 1, 2, 3, 4)
dialog.vbox.pack_start(table, True, True, 0)
dialog.vbox.pack_start(table, True, True, 10)
dialog.show_all()
return (dialog,enabled,name,command)
return (dialog,enabled,name,name_parse,command)
def on_last_exe_cmd(self, button, data):
new_data = data.copy()
new_data['dialog_vars'] = self.get_last_exe_cmd_dialog_vars()
self.on_new(button, new_data)
def on_new(self, button, data):
(dialog,enabled,name,command) = self._create_command_dialog()
#default values can be passed to dialogue window if required
enabled_var = ''
name_var = ''
name_parse_var= ''
command_var = ''
if data and 'dialog_vars' in data:
dialog_vars = data.get('dialog_vars', {})
enabled_var = dialog_vars.get('enabled', True)
name_var = dialog_vars.get('name', '')
name_parse_var= dialog_vars.get('name_parse', False)
command_var = dialog_vars.get('command', '')
(dialog,enabled,name,name_parse,command) = self._create_command_dialog(
enabled_var = enabled_var,
name_var = name_var,
name_parse_var = name_parse_var,
command_var = command_var)
res = dialog.run()
item = {}
if res == Gtk.ResponseType.ACCEPT:
item['enabled'] = enabled.get_active()
item['name'] = name.get_text()
item['name_parse'] = name_parse.get_active()
item['command'] = command.get_buffer().get_text(command.get_buffer().get_start_iter(), command.get_buffer().get_end_iter(), True)
if item['name'] == '' or item['command'] == '':
err = Gtk.MessageDialog(dialog,
@ -332,7 +516,9 @@ class CustomCommandsMenu(plugin.MenuItem):
err.destroy()
else:
# we have a new command
store = data['treeview'].get_model()
store = data['treeview'].get_model() if 'treeview' in data else None
if not store:
store = self.setup_store()
iter = store.get_iter_first()
name_exist = False
while iter != None:
@ -341,7 +527,8 @@ class CustomCommandsMenu(plugin.MenuItem):
break
iter = store.iter_next(iter)
if not name_exist:
store.append((item['enabled'], item['name'], item['command']))
store.append((item['enabled'], item['name'],
item['name_parse'], item['command']))
else:
gerr(_("Name *%s* already exist") % item['name'])
dialog.destroy()
@ -420,16 +607,17 @@ class CustomCommandsMenu(plugin.MenuItem):
if not iter:
return
(dialog,enabled,name,command) = self._create_command_dialog(
enabled_var = store.get_value(iter, CC_COL_ENABLED),
name_var = store.get_value(iter, CC_COL_NAME),
command_var = store.get_value(iter, CC_COL_COMMAND)
)
(dialog,enabled,name,name_parse,command) = self._create_command_dialog(
enabled_var = store.get_value(iter, CC_COL_ENABLED),
name_var = store.get_value(iter, CC_COL_NAME),
name_parse_var = store.get_value(iter, CC_COL_NAME_PARSE),
command_var = store.get_value(iter, CC_COL_COMMAND))
res = dialog.run()
item = {}
if res == Gtk.ResponseType.ACCEPT:
item['enabled'] = enabled.get_active()
item['name'] = name.get_text()
item['name_parse'] = name_parse.get_active()
item['command'] = command.get_buffer().get_text(command.get_buffer().get_start_iter(), command.get_buffer().get_end_iter(), True)
if item['name'] == '' or item['command'] == '':
err = Gtk.MessageDialog(dialog,
@ -452,14 +640,15 @@ class CustomCommandsMenu(plugin.MenuItem):
store.set(iter,
CC_COL_ENABLED,item['enabled'],
CC_COL_NAME, item['name'],
CC_COL_NAME_PARSE, item['name_parse'],
CC_COL_COMMAND, item['command']
)
else:
gerr(_("Name *%s* already exist") % item['name'])
dialog.destroy()
if __name__ == '__main__':
c = CustomCommandsMenu()
c.configure(None, None)

View File

@ -1,7 +1,5 @@
from gi.repository import Gtk
from terminatorlib.config import Config
from terminatorlib.terminal import Terminal
from terminatorlib.translation import _
import terminatorlib.plugin as plugin

View File

@ -48,6 +48,8 @@ class MouseFreeURLHandler(plugin.Plugin):
keyb = KeyBindUtil(config)
matches = []
matches_ptr = -1
vte = None
cur_term = None
#basic pattern
searchtext = "https?\:\/\/[^\s]+[\/\w]"
@ -64,16 +66,9 @@ class MouseFreeURLHandler(plugin.Plugin):
[PluginUrlLaunch, PluginUrlActLaunch, "<Alt>Return"])
def connect_signals(self):
#this is not giving list off all connected terminals in window
dbg("direct terminals: %s" % Terminator().terminals)
#get list of all terminals indirectly
terms = Terminator().terminals[0]
dbg("in-direct get terminals: %s" % terms.terminator.terminals)
for term in terms.terminator.terminals:
for term in Terminator().terminals:
dbg("signal connect term:%s" % term)
term.connect('tab-change', self.on_focus_in)
term.connect('focus-in', self.on_focus_in)
self.windows = Terminator().get_windows()
for window in self.windows:
@ -81,9 +76,7 @@ class MouseFreeURLHandler(plugin.Plugin):
def unload(self):
dbg("unloading")
#disconnect all signals and events
terms = Terminator().terminals[0]
for term in terms.terminator.terminals:
for term in Terminator().terminals:
try:
term.disconnect_by_func(self.on_focus_in)
except:
@ -107,23 +100,30 @@ class MouseFreeURLHandler(plugin.Plugin):
def extract(self):
#can we do extract more efficiently
col, row = self.vte.get_cursor_position()
(txt, attr) = self.vte.get_text_range(0,0,row, col)
(txt, attr) = self.vte.get_text_range_format(
Vte.Format.TEXT, 0, 0, row, col)
self.matches = re.findall(self.searchtext, txt)
self.matches_ptr = len(self.matches)-1
def get_term(self):
return Terminator().last_focused_term
def get_selected_url(self):
if len(self.matches):
dbg("found selected URL (%s %s %s)" %
(self.matches_ptr, self.matches[self.matches_ptr], self))
dbg("found selected URL (%s %s)" %
(self.matches_ptr, self.matches[self.matches_ptr]))
return self.matches[self.matches_ptr]
dbg("selected URL (%s %s)" % (self.matches_ptr, "not found"))
return None
def on_focus_in(self, widget, event):
dbg("focus-in clear url search buffer: %s" % self)
def get_focussed_terminal(self):
"""iterate over all the terminals to find which, if any, has focus"""
for terminal in Terminator().terminals:
if terminal.get_vte().has_focus():
return(terminal)
return(None)
def on_focus_in(self, widget, event = None):
dbg("focus-in clear url search buffer widget: %s" % widget)
self.cur_term = self.get_focussed_terminal()
self.vte = self.cur_term.get_vte()
self.clear_search()
def on_keypress(self, widget, event):
@ -160,8 +160,8 @@ class MouseFreeURLHandler(plugin.Plugin):
self.get_selected_url() # dbg url print
self.vte.copy_clipboard()
return True
self.vte.search_find_previous()
else:
self.vte.search_find_previous()
if self.matches_ptr > 0:
self.matches_ptr -= 1
@ -174,26 +174,44 @@ class MouseFreeURLHandler(plugin.Plugin):
if act == PluginUrlActEsc:
self.clear_search()
return
if act == PluginUrlActLaunch:
url = self.get_selected_url()
if url:
self.get_term().open_url(url, prepare=False)
self.cur_term.open_url(url, prepare=False)
return
#TODO: use case for KeyBindUtil
#So this is capturing <Return> key as if user presses return
#then the current selection would be cleared in case he types
#more commands or text in terminal has more urls now. So next
#time search should restart with complete text
#For KeyBindUtil if we register <Return> then keybinding will
#be shown in Preferences->Keybindings and if any other plugin
#wants to listen to same key code it will throw error since in
#UI binding has to be unique. May be we can have keybinds
#hidden from UI which plugins can use internally
if event.keyval == 65293: #<Return>
self.clear_search()
return
def clear_search(self):
self.matches = []
self.flag_http_on = False
self.matches_ptr = -1
if self.get_term():
self.vte = self.get_term().get_vte()
if self.vte:
self.vte.search_set_regex(None, 0)
dbg("search URL off")
self.vte.unselect_all()
def search(self):
dbg("searching text")
self.flag_http_on = True
self.vte = self.get_term().get_vte()
self.vte.search_set_wrap_around(True)
regex_flags_pcre2 = (regex.FLAGS_PCRE2 | regex.PCRE2_CASELESS)

View File

@ -1,4 +1,5 @@
import os
import signal
import sys
# Fix imports when testing this file directly
@ -44,9 +45,21 @@ class SaveLastSessionLayout(plugin.Plugin):
r = config.add_layout("SaveLastSessionLayout", current_layout)
config.save()
return True
def signal_handler(self,signum, frame):
signame = signal.Signals(signum).name
dbg('signal handler called:signal %s (%s)' %
(signame, signum))
self.save_session_layout()
def connect_signals(self):
dbg("SaveLastSessionLayout connect_signals")
signal.signal(signal.SIGTERM, self.signal_handler)
signal.signal(signal.SIGCHLD, self.signal_handler)
signal.signal(signal.SIGHUP, self.signal_handler)
n = 0
for term in Terminator().terminals:
dbg("SaveLastSessionLayout connect_signals to term num:(%d)" % n)

View File

@ -0,0 +1,69 @@
import os
import sys
# Fix imports when testing this file directly
if __name__ == '__main__':
sys.path.append( os.path.join(os.path.dirname(__file__), "../.."))
from gi.repository import Gtk,Vte
from terminatorlib.config import Config
import terminatorlib.plugin as plugin
from terminatorlib.translation import _
from terminatorlib.util import get_config_dir, err, dbg, gerr
from terminatorlib.terminator import Terminator
from terminatorlib import util
# AVAILABLE must contain a list of all the classes that you want exposed
AVAILABLE = ['SaveUserSessionLayout']
class SaveUserSessionLayout(plugin.MenuItem):
capabilities = ['terminal_menu', 'session']
config = None
conf_file = os.path.join(get_config_dir(),"save_last_session_cwd")
conf_sessions = []
emit_close_count = 0
vte_version = Vte.get_minor_version()
def __init__(self):
dbg("SaveUserSessionLayout Init")
plugin.MenuItem.__init__(self)
def callback(self, menuitems, menu, terminal):
""" Add save menu item to the menu"""
vte_terminal = terminal.get_vte()
item = Gtk.MenuItem.new_with_mnemonic(_('Save _UserSessionLayout'))
item.connect("activate", self.save_all_session_layouts, terminal)
menuitems.append(item)
def save_all_session_layouts(self, menuitem, terminal):
for term in Terminator().terminals:
self.save_session_layout("", "")
#not used, but capability can be used to load automatically
def load_session_layout(self, debugtab=False, widget=None, cwd=None, metadata=None, profile=None):
dbg("SaveUserSessionLayout load layout")
terminator = Terminator()
util.spawn_new_terminator(terminator.origcwd, ['-u', '-l', 'SaveUserSessionLayout'])
def save_session_layout(self, debugtab=False, widget=None, cwd=None, metadata=None, profile=None):
config = Config()
terminator = Terminator()
current_layout = terminator.describe_layout(save_cwd = True)
dbg("SaveUserSessionLayout: save layout(%s)" % current_layout)
res = config.replace_layout("SaveUserSessionLayout", current_layout)
if (not res):
r = config.add_layout("SaveUserSessionLayout", current_layout)
config.save()
return True
def close(self, term, event, arg1 = None):
if (self.emit_close_count == 0):
self.emit_close_count = self.emit_close_count + 1
self.save_session_layout("", "")

View File

@ -1,7 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.40.0 -->
<!-- Generated with glade 3.38.2 -->
<interface>
<requires lib="gtk+" version="3.10"/>
<object class="GtkListStore" id="AskBeforeCloseListStore">
<columns>
<!-- column-name askwhenclose -->
<column type="gchararray"/>
</columns>
<data>
<row>
<col id="0" translatable="yes">Never</col>
</row>
<row>
<col id="0" translatable="yes">Multiple Terminals</col>
</row>
<row>
<col id="0" translatable="yes">Always</col>
</row>
</data>
</object>
<object class="GtkListStore" id="BackspaceKeyListStore">
<columns>
<!-- column-name Result -->
@ -424,6 +441,7 @@
<property name="title" translatable="yes">Terminator Preferences</property>
<property name="default-width">640</property>
<property name="default-height">400</property>
<signal name="destroy" handler="on_destroy_event" swapped="no"/>
<child>
<object class="GtkBox" id="dialog_vbox1">
<property name="visible">True</property>
@ -472,7 +490,7 @@
<property name="spacing">36</property>
<property name="homogeneous">True</property>
<child>
<!-- n-columns=2 n-rows=8 -->
<!-- n-columns=2 n-rows=9 -->
<object class="GtkGrid" id="grid1">
<property name="visible">True</property>
<property name="can-focus">False</property>
@ -523,7 +541,7 @@
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
<property name="top-attach">2</property>
<property name="width">2</property>
</packing>
</child>
@ -540,7 +558,7 @@
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">2</property>
<property name="top-attach">3</property>
<property name="width">2</property>
</packing>
</child>
@ -557,7 +575,7 @@
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">3</property>
<property name="top-attach">4</property>
<property name="width">2</property>
</packing>
</child>
@ -574,7 +592,7 @@
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">4</property>
<property name="top-attach">5</property>
<property name="width">2</property>
</packing>
</child>
@ -591,7 +609,7 @@
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">5</property>
<property name="top-attach">6</property>
<property name="width">2</property>
</packing>
</child>
@ -608,7 +626,7 @@
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">6</property>
<property name="top-attach">7</property>
<property name="width">2</property>
</packing>
</child>
@ -625,10 +643,40 @@
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">7</property>
<property name="top-attach">8</property>
<property name="width">2</property>
</packing>
</child>
<child>
<object class="GtkComboBox" id="askbeforeclose">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="model">AskBeforeCloseListStore</property>
<property name="active">1</property>
<signal name="changed" handler="on_askbeforeclose_changed" swapped="no"/>
<child>
<object class="GtkCellRendererText"/>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Ask Before Closing:</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
@ -1241,7 +1289,7 @@
</packing>
</child>
<child>
<!-- n-columns=2 n-rows=4 -->
<!-- n-columns=2 n-rows=5 -->
<object class="GtkGrid" id="grid4">
<property name="visible">True</property>
<property name="can-focus">False</property>
@ -4410,6 +4458,21 @@ Much of the behavior of Terminator is based on GNOME Terminal, and we are adding
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="restoreconfigbutton">
<property name="label">Discard Changes</property>
<property name="use-action-appearance">False</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<signal name="clicked" handler="on_restoreconfigbutton_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="okbutton">
<property name="label">gtk-close</property>
@ -4423,7 +4486,7 @@ Much of the behavior of Terminator is based on GNOME Terminal, and we are adding
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
<property name="position">2</property>
</packing>
</child>
</object>

View File

@ -235,14 +235,25 @@ class PrefsEditor:
nb = guiget('notebook1')
nb.set_current_page(cur_page)
self.config.base.save_config_with_suffix('_cur')
def on_destroy_event(self, _widget):
self.config.base.remove_config_with_suffix('_cur')
def on_closebutton_clicked(self, _button):
"""Close the window"""
self.config.base.remove_config_with_suffix('_cur')
terminator = Terminator()
terminator.reconfigure()
self.window.destroy()
self.calling_window.preventHide = False
del(self)
def on_restoreconfigbutton_clicked(self, _button):
"""restore config to load time"""
self.config.base.restore_config_with_suffix('_cur')
self.on_closebutton_clicked(_button)
def set_values(self):
"""Update the preferences window with all the configuration from
Config()"""
@ -297,6 +308,18 @@ class PrefsEditor:
active = 0
widget = guiget('winstatecombo')
widget.set_active(active)
# Ask Before Closing
option = self.config['ask_before_closing']
if option == 'never':
active = 0
elif option == 'multiple_terminals':
active = 1
elif option == 'always':
active = 2
else:
active = 1
widget = guiget('askbeforeclose')
widget.set_active(active)
# Window borders
widget = guiget('winbordercheck')
widget.set_active(not self.config['borderless'])
@ -1486,7 +1509,20 @@ class PrefsEditor:
value = 'normal'
self.config['window_state'] = value
self.config.save()
def on_askbeforeclose_changed(self, widget):
"""Ask Before Close changed"""
selected = widget.get_active()
if selected == 0:
value = 'Never'
elif selected == 1:
value = 'Multiple Terminals'
elif selected == 2:
value = 'Always'
else:
value = 'Multiple Terminals'
configval = value.lower().replace(" ","_")
self.config['ask_before_closing'] = configval
self.config.save()
# helper function, not a signal
def addprofile(self, name, toclone):
"""Add a profile"""
@ -1583,6 +1619,14 @@ class PrefsEditor:
(model, rowiter) = selected.get_selected()
name = model.get_value(rowiter, 0)
config_layout = self.config.base.get_layout(name)
dbg("layout from terminator:(%s)" % current_layout)
dbg("layout from config:(%s)" % config_layout)
self.config.copy_layout_item(config_layout, current_layout, 'directory')
self.config.copy_layout_item(config_layout, current_layout, 'command')
dbg("updated layout from terminator:(%s)" % current_layout)
if self.config.replace_layout(name, current_layout):
treeview.set_cursor(model.get_path(rowiter), column=treeview.get_column(0), start_editing=False)
self.config.save()
@ -2152,7 +2196,7 @@ class LayoutEditor:
def on_layout_profile_workingdir_activate(self, widget):
"""A new working directory has been entered for this item"""
workdir = widget.get_text()
workdir = os.path.expanduser(widget.get_text())
layout = self.config.layout_get_config(self.layout_name)
layout[self.layout_item]['directory'] = workdir
self.config.save()

View File

@ -15,7 +15,7 @@ try:
except ImportError:
from urllib import unquote as urlunquote
from .util import dbg, err, spawn_new_terminator, make_uuid, manual_lookup, display_manager
from .util import dbg, err, spawn_new_terminator, make_uuid, manual_lookup
from . import util
from .config import Config
from .cwd import get_pid_cwd
@ -300,6 +300,7 @@ class Terminal(Gtk.VBox):
registry.load_plugins(force)
def _add_regex(self, name, re):
dbg(f"adding regex: {re}")
match = -1
if regex.FLAGS_PCRE2:
try:
@ -321,21 +322,25 @@ class Terminal(Gtk.VBox):
"""Update the regexps used to match URLs"""
userchars = "-A-Za-z0-9"
passchars = "-A-Za-z0-9,?;.:/!%$^*&~\"#'"
hostchars = "-A-Za-z0-9:\[\]"
hostchars = r"-A-Za-z0-9:\[\]"
pathchars = "-A-Za-z0-9_$.+!*(),;:@&=?/~#%'"
schemes = "(news:|telnet:|nntp:|file:/|https?:|ftps?:|webcal:|ssh:)"
schemes = "(news:|telnet:|nntp:|https?:|ftps?:|webcal:|ssh:)"
user = "[" + userchars + "]+(:[" + passchars + "]+)?"
urlpath = "/[" + pathchars + "]*[^]'.}>) \t\r\n,\\\"]"
lboundry = "\\b"
rboundry = "\\b"
re = (lboundry + "file:/" + "//?(:[0-9]+)?(" + urlpath + ")" +
rboundry + "/?")
self._add_regex('file', re)
re = (lboundry + schemes +
"//(" + user + "@)?[" + hostchars +".]+(:[0-9]+)?(" +
urlpath + ")?" + rboundry + "/?")
self._add_regex('full_uri', re)
if self.matches['full_uri'] == -1:
if self.matches['full_uri'] == -1 or self.matches['file'] == -1:
err ('Terminal::update_url_matches: Failed adding URL matches')
else:
re = (lboundry +
@ -345,18 +350,18 @@ class Terminal(Gtk.VBox):
self._add_regex('voip', re)
re = (lboundry +
"(www|ftp)[" + hostchars + "]*\.[" + hostchars +
"(www|ftp)[" + hostchars + r"]*\.[" + hostchars +
".]+(:[0-9]+)?(" + urlpath + ")?" + rboundry + "/?")
self._add_regex('addr_only', re)
re = (lboundry +
"(mailto:)?[a-zA-Z0-9][a-zA-Z0-9.+-]*@[a-zA-Z0-9]" +
"[a-zA-Z0-9-]*\.[a-zA-Z0-9][a-zA-Z0-9-]+" +
r"[a-zA-Z0-9-]*\.[a-zA-Z0-9][a-zA-Z0-9-]+" +
"[.a-zA-Z0-9-]*" + rboundry)
self._add_regex('email', re)
re = (lboundry +
"""news:[-A-Z\^_a-z{|}~!"#$%&'()*+,./0-9;:=?`]+@""" +
r"""news:[-A-Z\^_a-z{|}~!"#$%&'()*+,./0-9;:=?`]+@""" +
"[-A-Za-z0-9.]+(:[0-9]+)?" + rboundry)
self._add_regex('nntp', re)
@ -1507,7 +1512,7 @@ class Terminal(Gtk.VBox):
def set_cwd(self, cwd=None):
"""Set our cwd"""
if cwd is not None:
self.cwd = cwd
self.cwd = os.path.expanduser(cwd)
def held_open(self, widget=None, respawn=False, debugserver=False):
self.is_held_open = True

View File

@ -12,7 +12,6 @@ from .util import err, dbg, spawn_new_terminator
from .config import Config
from .prefseditor import PrefsEditor
from . import plugin
from .layoutlauncher import LayoutLauncher
class TerminalPopupMenu(object):
"""Class implementing the Terminal context menu"""

View File

@ -17,7 +17,6 @@ from .config import Config
from .keybindings import Keybindings
from .util import dbg, err, enumerate_descendants
from .factory import Factory
from .version import APP_NAME, APP_VERSION
from .translation import _
try:
@ -186,13 +185,6 @@ class Terminator(Borg):
for terminal in self.terminals:
dbg('checking: %s (%s)' % (terminal.uuid.urn, terminal))
if terminal.uuid.urn == uuid:
if terminal.get_toplevel().is_child_notebook():
topchild = terminal.get_toplevel().get_child()
current_page = topchild.get_current_page()
#we need to emit signal for plugin and retain same page
dbg("current_page for tab-change-signal:%s" % current_page)
terminal.emit('tab-change', current_page)
return terminal
return None
@ -339,7 +331,8 @@ class Terminator(Borg):
# For windows without a notebook ensure Terminal is visible and focused
if window_last_active_term_mapping[window]:
term = self.find_terminal_by_uuid(window_last_active_term_mapping[window].urn)
term.ensure_visible_and_focussed()
if term:
term.ensure_visible_and_focussed()
# Build list of new windows using prelayout list
new_win_list = []
@ -614,7 +607,7 @@ class Terminator(Borg):
def get_focussed_terminal(self):
"""iterate over all the terminals to find which, if any, has focus"""
for terminal in self.terminals:
if terminal.has_focus():
if terminal.get_vte().has_focus():
return(terminal)
return(None)

View File

@ -77,13 +77,17 @@ class Window(Container, Gtk.Window):
# self.set_property('allow-shrink', True) # FIXME FOR GTK3, or do we need this actually?
icon_to_apply=''
self.register_callbacks()
self.apply_config()
self.title = WindowTitle(self)
self.title.update()
self.preventHide = False
self.preventHide = False
self.display = Gdk.Display().get_default()
self.mouse = self.display.get_default_seat().get_pointer()
self.guake_key = None
options = self.config.options_get()
if options:
@ -92,15 +96,44 @@ class Window(Container, Gtk.Window):
if options.role:
self.set_role(options.role)
if options.forcedicon is not None:
icon_to_apply = options.forcedicon
if options.geometry:
if not self.parse_geometry(options.geometry):
err('Window::__init__: Unable to parse geometry: %s' %
err('Window::__init__: Unable to parse geometry: %s' %
options.geometry)
if options.guake_key:
self.guake_key = options.guake_key
if options.guake_side and options.guake_width and options.guake_height:
proceed_undecorated = True
if options.guake_side in ["top", "bottom", "left", "right"]:
self.guake_side = options.guake_side
else:
proceed_undecorated = False
err('Window::__init__: Unable to parse guake_side: %s' %
options.guake_side)
try:
self.guake_width = int(options.guake_width)
self.guake_height = int(options.guake_height)
except Exception as e:
proceed_undecorated = False
err('Window::__init__: Unable to parse guake_width: %s and/or guake_height: %s' %
options.guake_width, options.guake_height)
if proceed_undecorated:
self.set_decorated(False)
self.set_default_size(self.guake_width, self.guake_height)
else:
self.guake_key = None
self.register_callbacks()
self.apply_icon(icon_to_apply)
self.pending_set_rough_geometry_hint = False
self.hidefunc = self.hide
@ -119,6 +152,35 @@ class Window(Container, Gtk.Window):
else:
raise AttributeError('unknown property %s' % prop.name)
# NOTE: Gdk.VisibilityState.UNOBSCURED presumably isn't reliable due to transparency in moddern wms.
# Seems to work okay for our needs but should be kept in mind for future changes....
def _bind_window_to_position(self, widget, eve):
if eve.state == Gdk.VisibilityState.UNOBSCURED:
screen, mouse_x, mouse_y = self.mouse.get_position()
monitor = self.display.get_monitor_at_point(mouse_x, mouse_y)
window_w, window_h = self.guake_width, self.guake_height
geom_rect = monitor.get_geometry()
x, y, w, h = geom_rect.x, geom_rect.y, geom_rect.width, geom_rect.height
if not self.is_maximized() and not self.isfullscreen:
if self.guake_side == "top":
new_x = (w - (window_w + ((w - window_w)/2) )) + x
new_y = y
if self.guake_side == "bottom":
new_x = (w - (window_w + ((w - window_w)/2) )) + x
new_y = (h - window_h) + y
if self.guake_side == "left":
new_x = x
new_y = (h - (window_h + ((h - window_h)/2) )) + y
if self.guake_side == "right":
new_x = (w - window_w) + x
new_y = (h - (window_h + ((h - window_h)/2) )) + y
else:
new_x = x
new_y = y
self.move(new_x, new_y)
def register_callbacks(self):
"""Connect the GTK+ signals we care about"""
self.connect('key-press-event', self.on_key_press)
@ -129,22 +191,29 @@ class Window(Container, Gtk.Window):
self.connect('focus-out-event', self.on_focus_out)
self.connect('focus-in-event', self.on_focus_in)
if self.guake_key not in ('', None):
guake_unload_id = self.connect('visibility-notify-event', self._bind_window_to_position)
_hide_key = self.config['keybindings']['hide_window']
toggle_key = self.guake_key if self.guake_key not in ('', None) else _hide_key if _hide_key not in ('', None) else None
# Attempt to grab a global hotkey for hiding the window.
# If we fail, we'll never hide the window, iconifying instead.
if self.config['keybindings']['hide_window'] not in ('', None):
if display_manager() == 'X11':
try:
self.hidebound = Keybinder.bind(
self.config['keybindings']['hide_window'],
self.on_hide_window)
except (KeyError, NameError):
pass
if toggle_key and display_manager() == 'X11':
try:
self.hidebound = Keybinder.bind(toggle_key, self.on_hide_window)
except (KeyError, NameError):
...
if not self.hidebound:
err('Unable to bind hide_window key, another instance/window has it.')
self.hidefunc = self.iconify
else:
self.hidefunc = self.hide
if not self.hidebound:
err('Unable to bind hide_window key, another instance/window has it.')
self.hidefunc = self.iconify
if self.guake_key not in ('', None):
GObject.signal_handler_disconnect(self, guake_unload_id)
self.set_decorated(True)
else:
self.hidefunc = self.hide
def apply_config(self):
"""Apply various configuration options"""
@ -280,22 +349,15 @@ class Window(Container, Gtk.Window):
def on_delete_event(self, window, event, data=None):
"""Handle a window close request"""
maker = Factory()
if maker.isinstance(self.get_child(), 'Terminal'):
if self.is_zoomed():
return(self.confirm_close(window, _('window')))
else:
dbg('Only one child, closing is fine')
return(False)
elif maker.isinstance(self.get_child(), 'Container'):
return(self.confirm_close(window, _('window')))
else:
dbg('unknown child: %s' % self.get_child())
def confirm_close(self, window, type):
"""Display a confirmation dialog when the user is closing multiple
terminals in one window"""
return(not (self.construct_confirm_close(window, type) == Gtk.ResponseType.ACCEPT))
child = self.get_child()
if (maker.isinstance(child, 'Terminal') or
maker.isinstance(child, 'Container')):
confirm_close = self.construct_confirm_close(window, child)
return (confirm_close != Gtk.ResponseType.ACCEPT)
else:
dbg('unknown child: %s' % child)
return False # close anyway
def on_destroy_event(self, widget, data=None):
"""Handle window destruction"""
@ -342,7 +404,7 @@ class Window(Container, Gtk.Window):
# pylint: disable-msg=W0613
def on_window_state_changed(self, window, event):
"""Handle the state of the window changing"""
self.isfullscreen = bool(event.new_window_state &
self.isfullscreen = bool(event.new_window_state &
Gdk.WindowState.FULLSCREEN)
self.ismaximised = bool(event.new_window_state &
Gdk.WindowState.MAXIMIZED)
@ -401,7 +463,7 @@ class Window(Container, Gtk.Window):
visual = screen.get_rgba_visual()
if visual:
self.set_visual(visual)
def show(self, startup=False):
"""Undo the startup show request if started in hidden mode"""
#Present is necessary to grab focus when window is hidden from taskbar.
@ -491,7 +553,7 @@ class Window(Container, Gtk.Window):
container = maker.make('VPaned')
else:
container = maker.make('HPaned')
self.set_pos_by_ratio = True
if not sibling:
@ -515,7 +577,7 @@ class Window(Container, Gtk.Window):
for term in order:
container.add(term)
container.show_all()
while Gtk.events_pending():
Gtk.main_iteration_do(False)
sibling.grab_focus()
@ -563,7 +625,7 @@ class Window(Container, Gtk.Window):
self.set_property('term_zoomed', True)
if font_scale:
widget.cnxids.new(widget, 'size-allocate',
widget.cnxids.new(widget, 'size-allocate',
widget.zoom_scale, self.zoom_data)
widget.grab_focus()
@ -636,7 +698,7 @@ class Window(Container, Gtk.Window):
def get_terminals(self):
return(util.enumerate_descendants(self)[1])
def get_visible_terminals(self):
"""Walk down the widget tree to find all of the visible terminals.
Mostly using Container::get_visible_terminals()"""
@ -726,7 +788,7 @@ class Window(Container, Gtk.Window):
extra_height = win_height - total_font_height
dbg('setting geometry hints: (ewidth:%s)(eheight:%s),\
(fwidth:%s)(fheight:%s)' % (extra_width, extra_height,
(fwidth:%s)(fheight:%s)' % (extra_width, extra_height,
font_width, font_height))
geometry = Gdk.Geometry()
geometry.base_width = extra_width
@ -775,7 +837,7 @@ class Window(Container, Gtk.Window):
# change
child.set_current_page(child.get_current_page())
def set_groups(self, new_group, term_list):
def set_groups(self, new_group, term_list):
"""Set terminals in term_list to new_group"""
for terminal in term_list:
terminal.set_group(None, new_group)
@ -809,7 +871,7 @@ class Window(Container, Gtk.Window):
def group_win_toggle(self, widget):
"""Toggle grouping to all windows in the current window"""
if widget.group == 'Window':
if widget.group:
self.ungroup_win(widget)
else:
self.group_win(widget)
@ -850,7 +912,7 @@ class Window(Container, Gtk.Window):
if not maker.isinstance(notebook, 'Notebook'):
dbg('note in a notebook, refusing to ungroup tab')
return
self.set_groups(None, self.get_visible_terminals())
def move_tab(self, widget, direction):
@ -883,7 +945,7 @@ class Window(Container, Gtk.Window):
else:
err('unknown direction: %s' % direction)
return
notebook.reorder_child(child, page)
def navigate_terminal(self, terminal, direction):

View File

@ -30,7 +30,6 @@ False
"""
import os
import sys, os.path
sys.path.insert(0, os.path.realpath(os.path.join(os.path.dirname(__file__), "..")))