Skip to content

Commit

Permalink
Include names of processes in PromptQuitDialog
Browse files Browse the repository at this point in the history
  • Loading branch information
hackedd authored and Davidy22 committed Oct 21, 2022
1 parent 0c07f80 commit 246d879
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 25 deletions.
13 changes: 9 additions & 4 deletions guake/dialogs.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,20 @@ def __init__(self, parent, procs, tabs, notebooks):
else:
notebooks_str = ""

if procs == 0:
if not procs:
proc_str = _("There are no processes running")
elif procs == 1:
elif len(procs) == 1:
proc_str = _("There is a process still running")
else:
proc_str = _("There are {0} processes still running").format(procs)
proc_str = _("There are {0} processes still running").format(len(procs))

if procs:
proc_list = "\n\n" + "\n".join(f"{name} ({pid})" for pid, name in procs)
else:
proc_list = ""

self.set_markup(primary_msg)
self.format_secondary_markup(f"<b>{proc_str}{tab_str}{notebooks_str}.</b>")
self.format_secondary_markup(f"<b>{proc_str}{tab_str}{notebooks_str}.</b>{proc_list}")

def quit(self):
"""Run the "are you sure" dialog for quitting Guake"""
Expand Down
1 change: 1 addition & 0 deletions guake/globals.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ def is_run_from_git_workdir():
ALIGN_CENTER, ALIGN_LEFT, ALIGN_RIGHT = range(3)
ALIGN_TOP, ALIGN_BOTTOM = range(2)
ALWAYS_ON_PRIMARY = -1
PROMPT_NEVER, PROMPT_PROCESSES, PROMPT_ALWAYS = range(3)

# TODO this is not as fancy as as it could be
# pylint: disable=anomalous-backslash-in-string
Expand Down
10 changes: 8 additions & 2 deletions guake/guake_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@
from guake.dialogs import PromptQuitDialog
from guake.globals import MAX_TRANSPARENCY
from guake.globals import NAME
from guake.globals import PROMPT_ALWAYS
from guake.globals import PROMPT_PROCESSES
from guake.globals import TABS_SESSION_SCHEMA_VERSION
from guake.gsettings import GSettingHandler
from guake.keybindings import Keybindings
Expand Down Expand Up @@ -906,13 +908,17 @@ def accel_search_terminal(self, *args):

def accel_quit(self, *args):
"""Callback to prompt the user whether to quit Guake or not."""
procs = self.notebook_manager.get_running_fg_processes_count()
procs = self.notebook_manager.get_running_fg_processes()
tabs = self.notebook_manager.get_n_pages()
notebooks = self.notebook_manager.get_n_notebooks()
prompt_cfg = self.settings.general.get_boolean("prompt-on-quit")
prompt_tab_cfg = self.settings.general.get_int("prompt-on-close-tab")
# "Prompt on tab close" config overrides "prompt on quit" config
if prompt_cfg or (prompt_tab_cfg == 1 and procs > 0) or (prompt_tab_cfg == 2):
if (
prompt_cfg
or (prompt_tab_cfg == PROMPT_PROCESSES and procs)
or (prompt_tab_cfg == PROMPT_ALWAYS)
):
log.debug("Remaining procs=%r", procs)
if PromptQuitDialog(self.window, procs, tabs, notebooks).quit():
log.info("Quitting Guake")
Expand Down
41 changes: 22 additions & 19 deletions guake/notebook.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,12 @@
from guake.callbacks import MenuHideCallback
from guake.callbacks import NotebookScrollCallback
from guake.dialogs import PromptQuitDialog
from guake.globals import PROMPT_ALWAYS
from guake.globals import PROMPT_PROCESSES
from guake.menus import mk_notebook_context_menu
from guake.prefs import PrefsDialog
from guake.utils import gdk_is_x11_display
from guake.utils import get_process_name
from guake.utils import save_tabs_when_changed

import gi
Expand Down Expand Up @@ -247,15 +250,15 @@ def get_terminals(self):
terminals += page.get_terminals()
return terminals

def get_running_fg_processes_count(self):
fg_proc_count = 0
def get_running_fg_processes(self):
processes = []
for page in self.iter_pages():
fg_proc_count += self.get_running_fg_processes_count_page(self.page_num(page))
return fg_proc_count
processes += self.get_running_fg_processes_page(page)
return processes

def get_running_fg_processes_count_page(self, index):
total_procs = 0
for terminal in self.get_terminals_for_page(index):
def get_running_fg_processes_page(self, page):
processes = []
for terminal in page.get_terminals():
pty = terminal.get_pty()
if not pty:
continue
Expand All @@ -265,14 +268,13 @@ def get_running_fg_processes_count_page(self, index):
fgpid = posix.tcgetpgrp(fdpty)
log.debug("found running pid: %s", fgpid)
if fgpid not in (-1, term_pid):
total_procs += 1
processes.append((fgpid, get_process_name(fgpid)))
except OSError:
log.debug(
"Cannot retrieve any pid from terminal %s, looks like it is already dead",
index,
terminal,
)
return 0
return total_procs
return processes

def has_page(self):
return self.get_n_pages() > 0
Expand All @@ -296,16 +298,17 @@ def delete_page(self, page_num, kill=True, prompt=0):
if page_num >= self.get_n_pages() or page_num < 0:
log.error("Can not delete page %s no such index", page_num)
return

page = self.get_nth_page(page_num)
# TODO NOTEBOOK it would be nice if none of the "ui" stuff
# (PromptQuitDialog) would be in here
procs = self.get_running_fg_processes_count_page(page_num)
if prompt == 2 or (prompt == 1 and procs > 0):
procs = self.get_running_fg_processes_page(page)
if prompt == PROMPT_ALWAYS or (prompt == PROMPT_PROCESSES and procs):
# TODO NOTEBOOK remove call to guake
if not PromptQuitDialog(self.guake.window, procs, -1, None).close_tab():
return

page = self.get_nth_page(page_num)
for terminal in self.get_terminals_for_page(page_num):
for terminal in page.get_terminals():
if kill:
terminal.kill()
terminal.destroy()
Expand Down Expand Up @@ -609,8 +612,8 @@ def get_n_pages(self):
def get_n_notebooks(self):
return len(self.notebooks.keys())

def get_running_fg_processes_count(self):
r_fg_c = 0
def get_running_fg_processes(self):
processes = []
for k in self.notebooks:
r_fg_c += self.notebooks[k].get_running_fg_processes_count()
return r_fg_c
processes += self.notebooks[k].get_running_fg_processes()
return processes
6 changes: 6 additions & 0 deletions guake/tests/test_utils.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# -*- coding: utf-8 -*-
# pylint: disable=redefined-outer-name
import os

from guake.utils import FileManager
from guake.utils import get_process_name


def test_file_manager(fs):
Expand Down Expand Up @@ -37,3 +39,7 @@ def test_file_manager_clear(fs):
assert fm.read("/foo/bar") == "test"
fm.clear()
assert fm.read("/foo/bar") == "changed"


def test_process_name():
assert get_process_name(os.getpid())
14 changes: 14 additions & 0 deletions guake/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import enum
import logging
import os
import re
import subprocess
import time
import yaml
Expand Down Expand Up @@ -524,3 +525,16 @@ def draw(self, widget, cr):
cr.paint()

cr.restore()


def get_process_name(pid):
stat_file = f"/proc/{pid}/stat"
try:
with open(stat_file, "r", encoding="utf-8") as fp:
status = fp.read()
except IOError as ex:
log.debug("Unable to read %s: %s", stat_file, ex)
status = ""

match = re.match(r"\d+ \(([^)]+)\)", status)
return match.group(1) if match else None
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
release_summary: >
The "are you sure you want to close" dialog will now include names of any running processes.
features:
- |
- Include names of any processes in PromptQuitDialog, closes #256

0 comments on commit 246d879

Please sign in to comment.