[ABRT PATCH] dbus: check correct errno after dump_dir_is_accessible_by_uid()
by Jakub Filak
Signed-off-by: Jakub Filak <jfilak(a)redhat.com>
---
src/dbus/abrt-dbus.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/dbus/abrt-dbus.c b/src/dbus/abrt-dbus.c
index e3be4ce..9d7f1ff 100644
--- a/src/dbus/abrt-dbus.c
+++ b/src/dbus/abrt-dbus.c
@@ -523,7 +523,7 @@ static void handle_method_call(GDBusConnection *connection,
return;
}
- if (errno == ENOENT)
+ if (errno == ENOTDIR)
{
VERB1 log("Requested directory does not exist '%s'", problem_dir);
return_InvalidProblemDir_error(invocation, problem_dir);
@@ -575,7 +575,7 @@ static void handle_method_call(GDBusConnection *connection,
if (!dump_dir_accessible_by_uid(problem_dir, caller_uid))
{
- if (errno == ENOENT)
+ if (errno == ENOTDIR)
{
VERB1 log("Requested directory does not exist '%s'", problem_dir);
return_InvalidProblemDir_error(invocation, problem_dir);
@@ -755,7 +755,7 @@ static void handle_method_call(GDBusConnection *connection,
const char *dir_name = (const char*)l->data;
if (!dump_dir_accessible_by_uid(dir_name, caller_uid))
{
- if (errno == ENOENT)
+ if (errno == ENOTDIR)
{
VERB1 log("Requested directory does not exist '%s'", dir_name);
continue;
--
1.8.1.4
11 years, 1 month
[PATCH 1/2] reporter-rhtsupport: upload file to BigFileURL if it is large
by Denys Vlasenko
This patch adds BigFileURL and BigSizeMB parameters.
If uploaded DIR is bigger than BigSizeMB, then it is not attached
to the case, but uploaded to BigFileURL, then a comment is added
to the case with the URL of uploaded file.
Version 2: run-tested against actual server.
Signed-off-by: Denys Vlasenko <dvlasenk(a)redhat.com>
---
src/plugins/abrt_rh_support.c | 159 ++++++++++++++++++++++++++++++++++++++
src/plugins/abrt_rh_support.h | 7 ++
src/plugins/reporter-rhtsupport.c | 83 +++++++++++++++-----
src/plugins/rhtsupport.conf | 4 +
4 files changed, 232 insertions(+), 21 deletions(-)
diff --git a/src/plugins/abrt_rh_support.c b/src/plugins/abrt_rh_support.c
index 4e7465c..1e157ee 100644
--- a/src/plugins/abrt_rh_support.c
+++ b/src/plugins/abrt_rh_support.c
@@ -426,6 +426,165 @@ create_new_case(const char* base_url,
}
//
+// Add case comment
+//
+// $ curl -X POST -H 'Content-Type: application/xml' --data
+// '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+// <comment xmlns="http://www.redhat.com/gss/strata">
+// <text>Test comment! This can contain lots of information, etc.</text>
+// </comment>'
+// https://api.access.redhat.com/rs/cases/NNNNNNN/comments
+//
+static char*
+make_comment_data(const char *comment_text)
+{
+ char *retval;
+ xmlTextWriterPtr writer;
+ xmlBufferPtr buf;
+
+ buf = xxmlBufferCreate();
+ writer = xxmlNewTextWriterMemory(buf);
+
+ xxmlTextWriterStartDocument(writer, NULL, "UTF-8", "yes");
+ xxmlTextWriterStartElement(writer, "comment");
+ xxmlTextWriterWriteAttribute(writer, "xmlns",
+ "http://www.redhat.com/gss/strata");
+
+ xxmlTextWriterWriteElement(writer, "text", comment_text);
+
+ xxmlTextWriterEndDocument(writer);
+ retval = xstrdup((const char*)buf->content);
+ xmlFreeTextWriter(writer);
+ xmlBufferFree(buf);
+ return retval;
+}
+
+static rhts_result_t*
+post_comment_to_url(const char *url,
+ const char *username,
+ const char *password,
+ bool ssl_verify,
+ const char **additional_headers,
+ const char *comment_text)
+{
+ rhts_result_t *result = xzalloc(sizeof(*result));
+ char *url_copy = NULL;
+
+ char *xml = make_comment_data(comment_text);
+
+ int redirect_count = 0;
+ char *errmsg;
+ post_state_t *post_state;
+
+ redirect:
+ post_state = new_post_state(0
+ + POST_WANT_HEADERS
+ + POST_WANT_BODY
+ + POST_WANT_ERROR_MSG
+ + (ssl_verify ? POST_WANT_SSL_VERIFY : 0)
+ );
+ post_state->username = username;
+ post_state->password = password;
+
+ post_string(post_state, url, "application/xml", additional_headers, xml);
+
+ char *location = find_header_in_post_state(post_state, "Location:");
+
+ switch (post_state->http_resp_code)
+ {
+ case 404:
+ /* Not strictly necessary (default branch would deal with it too),
+ * but makes this typical error less cryptic:
+ * instead of returning html-encoded body, we show short concise message,
+ * and show offending URL (typos in which is a typical cause) */
+ result->error = -1;
+ result->msg = xasprintf("Error in HTTP POST, "
+ "HTTP code: 404 (Not found), URL:'%s'", url);
+ break;
+
+ case 301: /* "301 Moved Permanently" (for example, used to move http:// to https://) */
+ case 302: /* "302 Found" (just in case) */
+ case 305: /* "305 Use Proxy" */
+ if (++redirect_count < 10 && location)
+ {
+ free(url_copy);
+ url = url_copy = xstrdup(location);
+ free_post_state(post_state);
+ goto redirect;
+ }
+ /* fall through */
+
+ default:
+ result->error = -1;
+ errmsg = post_state->curl_error_msg;
+ if (errmsg && errmsg[0])
+ {
+ result->msg = xasprintf(_("Error in comment creation: %s"), errmsg);
+ }
+ else
+ {
+ errmsg = find_header_in_post_state(post_state, "Strata-Message:");
+ if (!errmsg)
+ errmsg = post_state->body;
+ if (errmsg && errmsg[0])
+ result->msg = xasprintf(_("Error in comment creation, HTTP code: %d, server says: '%s'"),
+ post_state->http_resp_code, errmsg);
+ else
+ result->msg = xasprintf(_("Error in comment creation, HTTP code: %d"),
+ post_state->http_resp_code);
+ }
+ break;
+
+ case 200:
+ case 201:
+ /* Created successfully */
+ result->url = xstrdup(location); /* note: xstrdup(NULL) returns NULL */
+ } /* switch (HTTP code) */
+
+ result->http_resp_code = post_state->http_resp_code;
+ result->body = post_state->body;
+ post_state->body = NULL;
+
+ free_post_state(post_state);
+ free(xml);
+ free(url_copy);
+ return result;
+}
+
+rhts_result_t*
+add_comment_to_case(const char* base_url,
+ const char* username,
+ const char* password,
+ bool ssl_verify,
+ const char* comment_text)
+{
+ char *url = concat_path_file(base_url, "comments");
+ rhts_result_t *result = post_comment_to_url(url,
+ username,
+ password,
+ ssl_verify,
+ // NB! text_plain_header here was causing error 404 instead of 201 (Created)!
+ // NULL makes curl use "Accept: */*" instead and creation works.
+ // Likely a bug on the server!
+ (const char **) NULL, //text_plain_header,
+ comment_text
+ );
+ free(url);
+
+ if (!result->error && !result->url)
+ {
+ /* Creation returned valid code, but no location */
+ result->error = -1;
+ free(result->msg);
+ result->msg = xasprintf(_("Error in comment creation: no Location URL, HTTP code: %d"),
+ result->http_resp_code
+ );
+ }
+
+ return result;
+}
+
+//
// Attach file to case
//
static rhts_result_t*
diff --git a/src/plugins/abrt_rh_support.h b/src/plugins/abrt_rh_support.h
index a20d3a1..22b6d79 100644
--- a/src/plugins/abrt_rh_support.h
+++ b/src/plugins/abrt_rh_support.h
@@ -70,6 +70,13 @@ create_new_case(const char* baseURL,
);
rhts_result_t*
+add_comment_to_case(const char* base_url,
+ const char* username,
+ const char* password,
+ bool ssl_verify,
+ const char* comment_text);
+
+rhts_result_t*
attach_file_to_case(const char* baseURL,
const char* username,
const char* password,
diff --git a/src/plugins/reporter-rhtsupport.c b/src/plugins/reporter-rhtsupport.c
index ffbef77..1183225 100644
--- a/src/plugins/reporter-rhtsupport.c
+++ b/src/plugins/reporter-rhtsupport.c
@@ -163,6 +163,15 @@ int create_tarball(const char *tempfile, problem_data_t *problem_data)
return 1; /* failure */
}
+static
+char *get_param_string(const char *name, map_string_h *settings, const char *dflt)
+{
+ char *envname = xasprintf("RHTSupport_%s", name);
+ const char *envvar = getenv(envname);
+ free(envname);
+ return xstrdup(envvar ? envvar : (get_map_string_item_or_NULL(settings, name) ? : dflt));
+}
+
int main(int argc, char **argv)
{
abrt_init(argv);
@@ -189,7 +198,8 @@ int main(int argc, char **argv)
"\n"
"If not specified, CONFFILE defaults to "CONF_DIR"/plugins/rhtsupport.conf\n"
"Its lines should have 'PARAM = VALUE' format.\n"
- "Recognized string parameters: URL, Login, Password.\n"
+ "Recognized string parameters: URL, Login, Password, BigFileURL.\n"
+ "Recognized numeric parameter: BigSizeMB.\n"
"Recognized boolean parameter (VALUE should be 1/0, yes/no): SSLVerify.\n"
"Parameters can be overridden via $RHTSupport_PARAM environment variables.\n"
"\n"
@@ -233,21 +243,21 @@ int main(int argc, char **argv)
VERB3 log("Loaded '%s'", fn);
conf_file = g_list_remove(conf_file, fn);
}
- char* envvar;
- char *url;
- char *login;
- char *password;
- bool ssl_verify;
- envvar = getenv("RHTSupport_URL");
- url = xstrdup(envvar ? envvar : (get_map_string_item_or_NULL(settings, "URL") ? : "https://api.access.redhat.com/rs"));
- envvar = getenv("RHTSupport_Login");
- login = xstrdup(envvar ? envvar : get_map_string_item_or_empty(settings, "Login"));
- envvar = getenv("RHTSupport_Password");
- password = xstrdup(envvar ? envvar : get_map_string_item_or_empty(settings, "Password"));
- envvar = getenv("RHTSupport_SSLVerify");
- ssl_verify = string_to_bool(envvar ? envvar : get_map_string_item_or_empty(settings, "SSLVerify"));
+ char *url = get_param_string("URL" , settings, "https://api.access.redhat.com/rs");
+ char *login = get_param_string("Login" , settings, "");
+ char *password = get_param_string("Password" , settings, "");
+ char *bigurl = get_param_string("BigFileURL", settings, "ftp://dropbox.redhat.com/incoming/");
if (!login[0] || !password[0])
error_msg_and_die(_("Empty RHTS login or password"));
+ char* envvar;
+ envvar = getenv("RHTSupport_SSLVerify");
+ bool ssl_verify = string_to_bool(
+ envvar ? envvar : (get_map_string_item_or_NULL(settings, "SSLVerify") ? : "1")
+ );
+ envvar = getenv("RHTSupport_BigSizeMB");
+ unsigned bigsize = xatoi_positive(
+ envvar ? envvar : (get_map_string_item_or_NULL(settings, "BigSizeMB") ? : "1000")
+ );
free_map_string(settings);
if (opts & OPT_t)
@@ -374,6 +384,7 @@ int main(int argc, char **argv)
if (tempfile_size <= QUERY_HINTS_IF_SMALLER_THAN)
{
/* Check for hints and show them if we have something */
+ log(_("Checking for hints"));
result = get_rhts_hints(url,
login,
password,
@@ -478,13 +489,43 @@ int main(int argc, char **argv)
result = NULL;
}
- /* Attach the tarball of -d DIR */
- result_atch = attach_file_to_case(url,
- login,
- password,
- ssl_verify,
- tempfile
- );
+ char *remote_filename = NULL;
+ if (bigsize != 0 && tempfile_size / (1024*1024) >= bigsize)
+ {
+ /* Upload tarball of -d DIR to "big file" FTP */
+ /* log(_("Uploading problem data to '%s'"), bigurl); - upload_file does this */
+ remote_filename = upload_file(bigurl, tempfile);
+ }
+ if (remote_filename)
+ {
+ log(_("Adding comment to case '%s'"), url);
+ /*
+ * Do not translate message below - it goes
+ * to a server where *other people* will read it.
+ */
+ char *comment_text = xasprintf(
+ "Problem data was uploaded to %s",
+ remote_filename
+ );
+ free(remote_filename);
+ result_atch = add_comment_to_case(url,
+ login, password,
+ ssl_verify,
+ comment_text
+ );
+ free(comment_text);
+ }
+ else
+ {
+ /* Attach the tarball of -d DIR */
+ log(_("Attaching problem data to case '%s'"), url);
+ result_atch = attach_file_to_case(url,
+ login, password,
+ ssl_verify,
+ tempfile
+
+ );
+ }
if (result_atch->error)
{
if (!(opts & OPT_t))
diff --git a/src/plugins/rhtsupport.conf b/src/plugins/rhtsupport.conf
index af3cde8..325be92 100644
--- a/src/plugins/rhtsupport.conf
+++ b/src/plugins/rhtsupport.conf
@@ -8,6 +8,10 @@
# URL=
# Login=
# Password=
+# BigFileURL=
+#
+# Integer parameter:
+# BigSizeMB=
#
# Boolean parameter:
# SSLVerify=
--
1.8.1.4
11 years, 1 month
[GNOME-ABRT PATCH 1/4] Rename attribute in errors.InvalidProblem
by Jakub Filak
Signed-off-by: Jakub Filak <jfilak(a)redhat.com>
---
src/gnome_abrt/errors.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/gnome_abrt/errors.py b/src/gnome_abrt/errors.py
index 2367aac..fffaf5e 100644
--- a/src/gnome_abrt/errors.py
+++ b/src/gnome_abrt/errors.py
@@ -25,7 +25,7 @@ class InvalidProblem(GnomeAbrtError):
def __init__(self, problem_id, message=None):
super(InvalidProblem, self).__init__(message)
- self.problem = problem_id
+ self.problem_id = problem_id
class UnavailableSource(GnomeAbrtError):
--
1.8.1.4
11 years, 1 month
[GNOME-ABRT PATCH 1/2] Use IOChannel approach in order to make signal handling synchronous
by Jakub Filak
- closes #17
Signed-off-by: Jakub Filak <jfilak(a)redhat.com>
---
src/gnome-abrt | 4 ++-
src/gnome_abrt/Makefile.am | 1 +
src/gnome_abrt/controller.py.in | 19 +++--------
src/gnome_abrt/signals.py | 71 +++++++++++++++++++++++++++++++++++++++++
4 files changed, 79 insertions(+), 16 deletions(-)
create mode 100644 src/gnome_abrt/signals.py
diff --git a/src/gnome-abrt b/src/gnome-abrt
index a277d36..8d4cf36 100755
--- a/src/gnome-abrt
+++ b/src/gnome-abrt
@@ -36,6 +36,7 @@ from gi.repository import Gio
import gnome_abrt
from gnome_abrt.views import OopsWindow
from gnome_abrt.controller import Controller
+from gnome_abrt.signals import glib_sigchld_signal_handler
from gnome_abrt.problems import MultipleSources
from gnome_abrt.directory_problems import DirectoryProblemSource
from gnome_abrt.dbus_problems import DBusProblemSource
@@ -189,7 +190,8 @@ class OopsApplication(Gtk.Application):
self.source = MultipleSources(sources)
- controller = Controller(self.source)
+ controller = Controller(self.source,
+ glib_sigchld_signal_handler)
main_window = OopsWindow(self, self.source, controller)
main_window.show_all()
self.add_window (main_window)
diff --git a/src/gnome_abrt/Makefile.am b/src/gnome_abrt/Makefile.am
index c390a2b..2635832 100644
--- a/src/gnome_abrt/Makefile.am
+++ b/src/gnome_abrt/Makefile.am
@@ -11,6 +11,7 @@ gnome_abrtexec_PYTHON = \
directory_problems.py \
errors.py \
problems.py \
+ signals.py \
tools.py \
views.py \
l10n.py \
diff --git a/src/gnome_abrt/controller.py.in b/src/gnome_abrt/controller.py.in
index f3898ac..f48e26d 100644
--- a/src/gnome_abrt/controller.py.in
+++ b/src/gnome_abrt/controller.py.in
@@ -18,24 +18,13 @@
import logging
import os
import sys
-import signal
class Controller(object):
- def __init__(self, source):
+ def __init__(self, source, sigchld_assign=None):
self.source = source
self.run_event_fn = self._first_event_run
-
- #pylint: disable=W0613
- def _handle_signal(self, signum):
- while True:
- try:
- os.wait3(os.WNOHANG)
- except OSError as ex:
- logging.debug(ex.message)
- break
-
- self.source.refresh()
+ self._sigchld_assign = sigchld_assign
def report(self, problem):
if not problem:
@@ -59,8 +48,8 @@ class Controller(object):
self.run_event_fn("open-gui", problem)
def _first_event_run(self, event, problem):
- signal.signal(signal.SIGCHLD,
- lambda signum, frame: self._handle_signal(signum))
+ if self._sigchld_assign is not None:
+ self._sigchld_assign(self.source.refresh)
self.run_event_fn = self._run_event_on_problem
self.run_event_fn(event, problem)
diff --git a/src/gnome_abrt/signals.py b/src/gnome_abrt/signals.py
new file mode 100644
index 0000000..d0d0b40
--- /dev/null
+++ b/src/gnome_abrt/signals.py
@@ -0,0 +1,71 @@
+## Copyright (C) 2013 ABRT team <abrt-devel-list(a)redhat.com>
+## Copyright (C) 2013 Red Hat, Inc.
+
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+## GNU General Public License for more details.
+
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
+
+import os
+import signal
+import logging
+import fcntl
+
+#pylint: disable=E0611
+from gi.repository import GLib
+
+#pylint: disable=W0613
+def _handle_signal_sigchld(callback, data):
+ while True:
+ try:
+ os.wait3(os.WNOHANG)
+ except OSError as ex:
+ # Breaks once no child is waiting
+ logging.debug(ex.message)
+ break
+
+ if data is not None:
+ callback(data)
+ else:
+ callback()
+
+def sigchld_signal_handler(callback, data=None):
+ signal.signal(signal.SIGCHLD,
+ lambda signum, frame: _handle_signal_sigchld(callback, data))
+
+
+#pylint: disable=W0613
+def _gsource_handle_signal(source, condition, data):
+ # Read all bytes, SIGCHLD could be received more than once but we want to
+ # call the callback only once. So, read all bytes from GIOChannel
+ while source.read():
+ pass
+
+ if data[1] is not None:
+ data[0](data[1])
+ else:
+ data[0]()
+
+def _giochannel_notice_sigchld_signal(wfd):
+ os.write(wfd, '1')
+
+def glib_sigchld_signal_handler(callback, data=None):
+ pipes = os.pipe()
+ fcntl.fcntl(pipes[0], fcntl.F_SETFD, fcntl.FD_CLOEXEC)
+ fcntl.fcntl(pipes[1], fcntl.F_SETFD, fcntl.FD_CLOEXEC)
+
+ sigchld_signal_handler(_giochannel_notice_sigchld_signal, pipes[1])
+
+ channel = GLib.IOChannel(pipes[0])
+ channel.set_flags(GLib.IOFlags.NONBLOCK)
+ channel.add_watch(GLib.IOCondition.IN,
+ _gsource_handle_signal, (callback, data))
--
1.8.1.4
11 years, 1 month
[GNOME-ABRT PATCH 1/6] Add pylint check and fix problems uncoverend by pylint
by Jakub Filak
Signed-off-by: Jakub Filak <jfilak(a)redhat.com>
---
Makefile.am | 3 +-
configure.ac | 10 +
gnome-abrt.spec.in | 5 +
pylintrc | 259 ++++++++++++++++++++++++
src/Makefile.am | 3 +
src/gnome-abrt | 173 ++++++++++------
src/gnome_abrt/__init__.py | 12 +-
src/gnome_abrt/application.py | 67 ++++---
src/gnome_abrt/config.py | 18 +-
src/gnome_abrt/controller.py.in | 17 +-
src/gnome_abrt/dbus_problems.py | 137 ++++++++-----
src/gnome_abrt/directory_problems.py | 140 ++++++++-----
src/gnome_abrt/l10n.py | 13 +-
src/gnome_abrt/problems.py | 157 +++++++++------
src/gnome_abrt/tools.py | 21 +-
src/gnome_abrt/views.py | 374 +++++++++++++++++++----------------
src/gnome_abrt/wrappers/Makefile.am | 8 +
src/gnome_abrt/wrappers/__init__.py | 2 +-
18 files changed, 946 insertions(+), 473 deletions(-)
create mode 100644 pylintrc
diff --git a/Makefile.am b/Makefile.am
index 37290c8..365a73c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,7 +1,7 @@
ACLOCAL_AMFLAGS = -I m4
SUBDIRS = src po doc icons
-EXTRA_DIST = gnome-abrt.spec.in asciidoc.conf gnome-abrt-version
+EXTRA_DIST = gnome-abrt.spec.in asciidoc.conf gnome-abrt-version pylintrc
RPM_DIRS = --define "_sourcedir `pwd`" \
--define "_rpmdir `pwd`" \
@@ -23,7 +23,6 @@ srpm:
rpmbuild $(RPM_DIRS) -bs gnome-abrt.spec
run: all dist
- cp src/gnome_abrt/wrappers/.libs/_wrappers.so src/gnome_abrt/wrappers/
PYTHONPATH="../src" ./src/gnome-abrt $(ARGS)
UPLOAD_URL ?= fedorahosted.org:abrt
diff --git a/configure.ac b/configure.ac
index b8fc9da..03cfdf5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -46,6 +46,16 @@ AC_PATH_PROG([XMLTO], [xmlto], [no])
[exit 1]
[fi]
+# make check
+AC_PATH_PROG([PYLINT], [pylint], [no])
+[if test "$PYLINT" = "no"]
+[then]
+ [echo "The pylint program was not found in the search path. Please ensure"]
+ [echo "that it is installed and its directory is included in the search path."]
+ [echo "Then run configure again before attempting to build faf."]
+ [exit 1]
+[fi]
+
dnl ****** INTERNATIONALIZATION **********************
GETTEXT_PACKAGE=gnome-abrt
diff --git a/gnome-abrt.spec.in b/gnome-abrt.spec.in
index f3ab511..7d6d4da 100644
--- a/gnome-abrt.spec.in
+++ b/gnome-abrt.spec.in
@@ -24,6 +24,7 @@ BuildRequires: xmlto
BuildRequires: pygobject3-devel
BuildRequires: libreport-gtk-devel > 2.0.20
BuildRequires: gtk3-devel
+BuildRequires: pylint
Requires: python-inotify
Requires: pygobject3
@@ -58,6 +59,10 @@ desktop-file-install \
${RPM_BUILD_ROOT}%{_datadir}/applications/%{name}.desktop
+%check
+make check
+
+
%post
# update icon cache
touch --no-create %{_datadir}/icons/hicolor &>/dev/null || :
diff --git a/pylintrc b/pylintrc
new file mode 100644
index 0000000..5f791b4
--- /dev/null
+++ b/pylintrc
@@ -0,0 +1,259 @@
+[MASTER]
+
+# Specify a configuration file.
+#rcfile=
+
+# Python code to execute, usually for sys.path manipulation such as
+# pygtk.require().
+#init-hook=
+
+# Profiled execution.
+profile=no
+
+# Add files or directories to the blacklist. They should be base names, not
+# paths.
+ignore=.git,gnome_abrt_glade.py
+
+# Pickle collected data for later comparisons.
+persistent=yes
+
+# List of plugins (as comma separated values of python modules names) to load,
+# usually to register additional checkers.
+load-plugins=
+
+
+[MESSAGES CONTROL]
+
+# Enable the message, report, category or checker with the given id(s). You can
+# either give multiple identifier separated by comma (,) or put this option
+# multiple time.
+#enable=
+
+# Disable the message, report, category or checker with the given id(s). You
+# can either give multiple identifier separated by comma (,) or put this option
+# multiple time (only on the command line, not in the configuration file where
+# it should appear only once).
+disable=C0111,W0212,R0201,R0903,I0011,W0603,W0622,I0001
+
+
+[REPORTS]
+
+# Set the output format. Available formats are text, parseable, colorized, msvs
+# (visual studio) and html. You can also give a reporter class, eg
+# mypackage.mymodule.MyReporterClass.
+output-format=colorized
+
+# Include message's id in output
+include-ids=yes
+
+# Include symbolic ids of messages in output
+symbols=no
+
+# Put messages in a separate file for each module / package specified on the
+# command line instead of printing them on stdout. Reports (if any) will be
+# written in a file name "pylint_global.[txt|html]".
+files-output=no
+
+# Tells whether to display a full report or only the messages
+reports=no
+
+# Python expression which should return a note less than 10 (10 is the highest
+# note). You have access to the variables errors warning, statement which
+# respectively contain the number of errors / warnings messages and the total
+# number of statements analyzed. This is used by the global evaluation report
+# (RP0004).
+evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
+
+# Add a comment according to your evaluation note. This is used by the global
+# evaluation report (RP0004).
+comment=no
+
+
+[MISCELLANEOUS]
+
+# List of note tags to take in consideration, separated by a comma.
+notes=FIXME
+
+
+[BASIC]
+
+# Required attributes for module, separated by a comma
+required-attributes=
+
+# List of builtins function names that should not be used, separated by a comma
+bad-functions=apply,input
+
+# Regular expression which should only match correct module names
+module-rgx=((gnome-abrt)|([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
+
+# Regular expression which should only match correct module level names
+const-rgx=(([A-Z_][A-Z1-9_]*)|(__.*__))$
+
+# Regular expression which should only match correct class names
+class-rgx=[A-Z_][a-zA-Z0-9]+$
+
+# Regular expression which should only match correct function names
+function-rgx=[a-z_][a-z0-9_]{2,40}$
+
+# Regular expression which should only match correct method names
+method-rgx=[a-z_][a-z0-9_]{2,40}$
+
+# Regular expression which should only match correct instance attribute names
+attr-rgx=[a-z_][a-z0-9_]{2,40}$
+
+# Regular expression which should only match correct argument names
+argument-rgx=[a-z_][a-z0-9_]{2,40}$
+
+# Regular expression which should only match correct variable names
+variable-rgx=[a-z_][a-z0-9_]{2,40}$
+
+# Regular expression which should only match correct list comprehension /
+# generator expression variable names
+inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
+
+# Good variable names which should always be accepted, separated by a comma
+good-names=p,i,j,k,ex,Run,_,dd
+
+# Bad variable names which should always be refused, separated by a comma
+bad-names=foo,bar,baz,toto,tutu,tata
+
+# Regular expression which should only match functions or classes name which do
+# not require a docstring
+no-docstring-rgx=__.*__
+
+
+[TYPECHECK]
+
+# Tells whether missing members accessed in mixin class should be ignored. A
+# mixin class is detected if its name ends with "mixin" (case insensitive).
+ignore-mixin-members=yes
+
+# List of classes names for which member attributes should not be checked
+# (useful for classes with attributes dynamically set).
+ignored-classes=SQLObject
+
+# When zope mode is activated, add a predefined set of Zope acquired attributes
+# to generated-members.
+zope=no
+
+# List of members which are set dynamically and missed by pylint inference
+# system, and so shouldn't trigger E0201 when accessed. Python regular
+# expressions are accepted.
+generated-members=REQUEST,acl_users,aq_parent,get_windows,show_all,add_action,quit,run,set_flags,set_app_menu,activate,add_window,connect,set_default_size,get_style_context,add_accel_group
+
+
+[VARIABLES]
+
+# Tells whether we should check for unused import in __init__ files.
+init-import=no
+
+# A regular expression matching the beginning of the name of dummy variables
+# (i.e. not used).
+dummy-variables-rgx=_|dummy
+
+# List of additional names supposed to be defined in builtins. Remember that
+# you should avoid to define new builtins when possible.
+additional-builtins=
+
+
+[SIMILARITIES]
+
+# Minimum lines number of a similarity.
+min-similarity-lines=10
+
+# Ignore comments when computing similarities.
+ignore-comments=yes
+
+# Ignore docstrings when computing similarities.
+ignore-docstrings=yes
+
+# Ignore imports when computing similarities.
+ignore-imports=no
+
+
+[FORMAT]
+
+# Maximum number of characters on a single line.
+max-line-length=80
+
+# Maximum number of lines in a module
+max-module-lines=1000
+
+# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
+# tab).
+indent-string=' '
+
+
+[DESIGN]
+
+# Maximum number of arguments for function / method
+max-args=12
+
+# Argument names that match this expression will be ignored. Default to name
+# with leading underscore
+ignored-argument-names=_.*
+
+# Maximum number of locals for function / method body
+max-locals=30
+
+# Maximum number of return / yield for function / method body
+max-returns=12
+
+# Maximum number of branch for function / method body
+max-branchs=30
+
+# Maximum number of statements in function / method body
+max-statements=60
+
+# Maximum number of parents for a class (see R0901).
+max-parents=7
+
+# Maximum number of attributes for a class (see R0902).
+max-attributes=20
+
+# Minimum number of public methods for a class (see R0903).
+min-public-methods=0
+
+# Maximum number of public methods for a class (see R0904).
+max-public-methods=20
+
+
+[IMPORTS]
+
+# Deprecated modules which should not be used, separated by a comma
+deprecated-modules=regsub,string,TERMIOS,Bastion,rexec
+
+# Create a graph of every (i.e. internal and external) dependencies in the
+# given file (report RP0402 must not be disabled)
+import-graph=
+
+# Create a graph of external dependencies in the given file (report RP0402 must
+# not be disabled)
+ext-import-graph=
+
+# Create a graph of internal dependencies in the given file (report RP0402 must
+# not be disabled)
+int-import-graph=
+
+
+[CLASSES]
+
+# List of interface methods to ignore, separated by a comma. This is used for
+# instance to not check methods defines in Zope's Interface base class.
+ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by
+
+# List of method names used to declare (i.e. assign) instance attributes.
+defining-attr-methods=__init__,__new__
+
+# List of valid names for the first argument in a class method.
+valid-classmethod-first-arg=cls
+
+# List of valid names for the first argument in a metaclass class method.
+valid-metaclass-classmethod-first-arg=mcs
+
+
+[EXCEPTIONS]
+
+# Exceptions that will emit a warning when being caught. Defaults to
+# "Exception"
+overgeneral-exceptions=Exception
diff --git a/src/Makefile.am b/src/Makefile.am
index e34b536..7bfaada 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -8,3 +8,6 @@ desktop_in_files = gnome-abrt.desktop.in
desktop_DATA = $(desktop_in_files:.desktop.in=.desktop)
EXTRA_DIST = $(bin_SCRIPTS) $(desktop_in_files)
+
+check-local: $(bin_SCRIPTS)
+ $(PYLINT) --rcfile=$(top_builddir)/pylintrc $^ ./gnome_abrt
diff --git a/src/gnome-abrt b/src/gnome-abrt
index 0fb07ef..56a2623 100755
--- a/src/gnome-abrt
+++ b/src/gnome-abrt
@@ -25,13 +25,21 @@ import signal
from argparse import ArgumentParser
# pygobject
+#pylint: disable=E0611
from gi.repository import Gtk
+#pylint: disable=E0611
from gi.repository import GLib
+#pylint: disable=E0611
from gi.repository import Gio
-from gi.repository import GObject
# gnome-abrt
import gnome_abrt
+from gnome_abrt.views import OopsWindow
+from gnome_abrt.controller import Controller
+from gnome_abrt.problems import MultipleSources
+from gnome_abrt.directory_problems import DirectoryProblemSource
+from gnome_abrt.dbus_problems import DBusProblemSource
+from gnome_abrt.errors import UnavailableSource
from gnome_abrt.l10n import _
from gnome_abrt.wrappers import show_events_list_dialog
from gnome_abrt.config import get_configuration
@@ -41,14 +49,20 @@ import dbus
import dbus.service
from dbus.mainloop.glib import DBusGMainLoop
-GNOME_ABRT_APPLICATION_ID='org.freedesktop.GnomeAbrt'
-GNOME_ABRT_INTERFACE='org.freedesktop.GnomeAbrt'
-GNOME_ABRT_OBJECT_PATH='/org/freedesktop/GnomeAbrt'
+GNOME_ABRT_APPLICATION_ID = 'org.freedesktop.GnomeAbrt'
+GNOME_ABRT_INTERFACE = 'org.freedesktop.GnomeAbrt'
+GNOME_ABRT_OBJECT_PATH = '/org/freedesktop/GnomeAbrt'
# because of https://bugzilla.gnome.org/show_bug.cgi?id=682331
-class GtkApplicationDBUSImpl(object):
+class GtkAppDBUSImpl(object):
+ """A proxy for primary application
+ """
+
class Service(dbus.service.Object):
+ """DBus service sitting on session bus
+ """
+
def __init__(self, bus, bus_name, application):
bus_name = dbus.service.BusName(bus_name, bus)
dbus.service.Object.__init__(self, bus_name, GNOME_ABRT_OBJECT_PATH)
@@ -57,14 +71,21 @@ class GtkApplicationDBUSImpl(object):
@dbus.service.method(dbus_interface=GNOME_ABRT_INTERFACE,
in_signature='as', out_signature='')
def command_line(self, argv):
+ """DBus service method accepting a new command line arguments
+ """
+
class Arguments(object):
+ """Adapter for Gtk class
+ """
+
def __init__(self, argv):
self._argv = argv
def get_arguments(self):
return self._argv
- self._app._parse_command_line(self, Arguments([str(a) for a in argv]))
+ args = Arguments([str(a) for a in argv])
+ self._app._parse_command_line(self, args)
def __init__(self, bus_name, application):
@@ -79,17 +100,28 @@ class GtkApplicationDBUSImpl(object):
if bus.name_has_owner(bus_name):
self._primary_obj = bus.get_object(bus_name, GNOME_ABRT_OBJECT_PATH)
else:
- self._service = GtkApplicationDBUSImpl.Service(bus, bus_name, self._app)
+ self._service = GtkAppDBUSImpl.Service(bus, bus_name, self._app)
+
def is_remote(self):
- return not not self._primary_obj
+ """Application is remote if connection to primary application succeeded
+ """
+
+ return self._primary_obj is not None
+
def send_command_line(self, argv):
+ """Sends command line arguments to the primary application.
+ Raises RuntimeError if an instance is not remote.
+ """
+
if not self.is_remote():
- raise RuntimeError("Can't send command-line message because instance is not a remote application")
+ raise RuntimeError("Can't send command-line message because "
+ "instance is not a remote application")
if not self._primary_iface:
- self._primary_iface = dbus.Interface(self._primary_obj, GNOME_ABRT_INTERFACE)
+ self._primary_iface = dbus.Interface(self._primary_obj,
+ GNOME_ABRT_INTERFACE)
if len(argv) == 0:
argv = dbus.Array([], signature='s')
@@ -100,12 +132,15 @@ class GtkApplicationDBUSImpl(object):
class OopsApplication(Gtk.Application):
def __init__(self):
- super(OopsApplication, self).__init__()
+ Gtk.Application.__init__(self)
- self._dbus_srv = GtkApplicationDBUSImpl(GNOME_ABRT_APPLICATION_ID, self)
+ self._dbus_srv = GtkAppDBUSImpl(GNOME_ABRT_APPLICATION_ID, self)
self.connect("command-line", self._parse_command_line)
self.set_flags(Gio.ApplicationFlags.HANDLES_COMMAND_LINE)
+ self.gcontext = None
+ self.source = None
+ #pylint: disable=W0613
def _parse_command_line(self, sender, gcmdargs):
argv = gcmdargs.get_arguments()
@@ -114,7 +149,7 @@ class OopsApplication(Gtk.Application):
return 0
if len(argv) > 0:
- conf = gnome_abrt.get_configuration()
+ conf = get_configuration()
conf['problemid'] = argv[0]
self.activate()
@@ -126,33 +161,35 @@ class OopsApplication(Gtk.Application):
if windows:
windows[0].present()
else:
- conf = gnome_abrt.get_configuration()
+ conf = get_configuration()
conf.add_option("all_problems", default_value=False)
sources = []
try:
- sources.append(gnome_abrt.DBusProblemSource(self._dbus_srv.mainloop))
- except gnome_abrt.UnavailableSource as e:
- logging.warning(e.message)
+ sources.append(DBusProblemSource(self._dbus_srv.mainloop))
+ except UnavailableSource as ex:
+ logging.warning(ex.message)
- # TODO : really ? move it somewhere else ...
self.gcontext = GLib.main_context_default()
try:
- # TODO : pass the directory over command line
- sources.append(gnome_abrt.DirectoryProblemSource(os.path.join(GLib.get_user_cache_dir(), "abrt/spool"), context=self.gcontext))
- except gnome_abrt.UnavailableSource as e:
- logging.warning(e.message)
+ path = os.path.join(GLib.get_user_cache_dir(), "abrt/spool")
+ dps = DirectoryProblemSource(path, context=self.gcontext)
+ sources.append(dps)
+ except UnavailableSource as ex:
+ logging.warning(ex.message)
if len(sources) == 0:
- raise gnome_abrt.UnavailableSource("No available problem source.")
+ raise UnavailableSource("No available problem source.")
- self.source = gnome_abrt.MultipleSources(*sources)
+ self.source = MultipleSources(sources)
- main_window = gnome_abrt.OopsWindow(self, self.source, gnome_abrt.Controller(self.source))
+ controller = Controller(self.source)
+ main_window = OopsWindow(self, self.source, controller)
main_window.show_all()
self.add_window (main_window)
- except Exception as e:
- logging.exception(e.message)
+ #pylint: disable=W0703
+ except Exception as ex:
+ logging.exception(ex.message)
sys.exit(1)
def do_startup(self):
@@ -164,19 +201,20 @@ class OopsApplication(Gtk.Application):
menu.append(_("_Quit"), "app.quit")
action = Gio.SimpleAction.new("preferences", None)
- action.connect("activate", self.on_action_prefrences);
- self.add_action(action);
+ action.connect("activate", self.on_action_prefrences)
+ self.add_action(action)
action = Gio.SimpleAction.new("about", None)
- action.connect("activate", self.on_action_about);
- self.add_action(action);
+ action.connect("activate", self.on_action_about)
+ self.add_action(action)
action = Gio.SimpleAction.new("quit", None)
- action.connect("activate", self.on_action_quit);
- self.add_action(action);
+ action.connect("activate", self.on_action_quit)
+ self.add_action(action)
self.set_app_menu(menu)
+ #pylint: disable=W0613
def on_action_prefrences(self, action, parameter):
windows = self.get_windows()
if windows:
@@ -184,31 +222,33 @@ class OopsApplication(Gtk.Application):
else:
show_events_list_dialog()
+ #pylint: disable=W0613
def on_action_about(self, action, parameter):
dialog = Gtk.AboutDialog()
- dialog.set_icon_name("abrt");
- #dialog.set_version(VERSION);
- dialog.set_logo_icon_name("abrt");
- dialog.set_program_name("ABRT");
- dialog.set_copyright("Copyright © 2012 Red Hat, Inc");
+ dialog.set_icon_name("abrt")
+ #dialog.set_version(VERSION)
+ dialog.set_logo_icon_name("abrt")
+ dialog.set_program_name("ABRT")
+ dialog.set_copyright("Copyright © 2012 Red Hat, Inc")
dialog.set_license(
- "This program is free software; you can redistribut"
- "e it and/or modify it under the terms of the GNU General Public License "
- "as published by the Free Software Foundation; either version 2 of the Li"
- "cense, or (at your option) any later version.\n\nThis program is distrib"
- "uted in the hope that it will be useful, but WITHOUT ANY WARRANTY; witho"
- "ut even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICU"
- "LAR PURPOSE. See the GNU General Public License for more details.\n\nYo"
- "u should have received a copy of the GNU General Public License along wi"
- "th this program. If not, see <http://www.gnu.org/licenses/>.");
- dialog.set_wrap_license(True);
- dialog.set_website("https://fedorahosted.org/abrt/");
- dialog.set_authors(["ABRT Team"]);
- #dialog.set_artists(artists);
- #dialog.set_translator_credits(_("translator-credits"));
+ "This program is free software; you can redistribut"
+ "e it and/or modify it under the terms of the GNU General Public License "
+ "as published by the Free Software Foundation; either version 2 of the Li"
+ "cense, or (at your option) any later version.\n\nThis program is distrib"
+ "uted in the hope that it will be useful, but WITHOUT ANY WARRANTY; witho"
+ "ut even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICU"
+ "LAR PURPOSE. See the GNU General Public License for more details.\n\nYo"
+ "u should have received a copy of the GNU General Public License along wi"
+ "th this program. If not, see <http://www.gnu.org/licenses/>.")
+ dialog.set_wrap_license(True)
+ dialog.set_website("https://fedorahosted.org/abrt/")
+ dialog.set_authors(["ABRT Team"])
+ #dialog.set_artists(artists)
+ #dialog.set_translator_credits(_("translator-credits"))
dialog.run()
dialog.destroy()
+ #pylint: disable=W0613
def on_action_quit(self, action, parameter):
self.quit()
@@ -218,9 +258,12 @@ if __name__ == "__main__":
gnome_abrt.init()
- CMDARGS = ArgumentParser(description = _('View and report application crashes'))
- CMDARGS.add_argument('-v', '--verbose', action='count', help=_('Be verbose'))
- CMDARGS.add_argument('-p', '--problem', help=_('Selected problem ID'))
+ CMDARGS = ArgumentParser(
+ description = _('View and report application crashes'))
+ CMDARGS.add_argument('-v', '--verbose', action='count',
+ help=_('Be verbose'))
+ CMDARGS.add_argument('-p', '--problem',
+ help=_('Selected problem ID'))
OPTIONS = CMDARGS.parse_args()
@@ -229,19 +272,19 @@ if __name__ == "__main__":
VARS = vars(OPTIONS)
- conf = get_configuration();
+ CONF = get_configuration()
# TODO : mark this option as hidden or something like that
- conf.add_option('problemid', default_value=None)
+ CONF.add_option('problemid', default_value=None)
- app_cmdline = []
+ APP_CMDLINE = []
if 'problem' in VARS:
- app_cmdline.append(VARS['problem'])
+ APP_CMDLINE.append(VARS['problem'])
- exit_code = 1
- app = OopsApplication()
+ EXIT_CODE = 1
+ APP = OopsApplication()
try:
- exit_code = app.run(app_cmdline)
- except gnome_abrt.UnavailableSource as e:
- logging.error(e.message)
+ EXIT_CODE = APP.run(APP_CMDLINE)
+ except UnavailableSource as ex:
+ logging.error(ex.message)
- sys.exit(exit_code)
+ sys.exit(EXIT_CODE)
diff --git a/src/gnome_abrt/__init__.py b/src/gnome_abrt/__init__.py
index f3bdc38..178bbd2 100644
--- a/src/gnome_abrt/__init__.py
+++ b/src/gnome_abrt/__init__.py
@@ -15,14 +15,6 @@
## along with this program; if not, write to the Free Software
## Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
-from config import get_configuration
-from views import OopsWindow
-from problems import (ProblemSource, Problem, MultipleSources)
-from dbus_problems import DBusProblemSource
-from directory_problems import DirectoryProblemSource
-from controller import Controller
-from errors import (UnavailableSource, InvalidProblem)
-import l10n
-
def init():
- l10n.init('gnome-abrt')
+ import gnome_abrt.l10n
+ gnome_abrt.l10n.init()
diff --git a/src/gnome_abrt/application.py b/src/gnome_abrt/application.py
index ac38324..392272e 100644
--- a/src/gnome_abrt/application.py
+++ b/src/gnome_abrt/application.py
@@ -16,14 +16,15 @@
## Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
import os
-import sys
import logging
-from itertools import ifilter
# PyGObject
import gi
+#pylint: disable=E0611
from gi.repository import Gtk
+#pylint: disable=E0611
from gi.repository import Gio
+#pylint: disable=E0611
from gi.repository import GdkPixbuf
class Application(object):
@@ -42,38 +43,42 @@ class Application(object):
__globa_app_cache__ = {}
-def compare_executable(executable, de):
+def compare_executable(executable, desktop_entry):
if not executable:
return False
- dexec = de.get_executable()
+ dexec = desktop_entry.get_executable()
realpath = None
if executable[0] == '/' and os.path.islink(executable):
realpath = os.readlink(executable)
if realpath[0] != '/':
- realpath = os.path.abspath(os.path.join(os.path.dirname(executable), realpath))
+ realpath = os.path.abspath(
+ os.path.join(os.path.dirname(executable), realpath))
if realpath == executable:
realpath = None
- return os.path.basename(executable) == os.path.basename(dexec) or executable == dexec or (realpath and compare_executable(realpath, de))
+ return (os.path.basename(executable) == os.path.basename(dexec)
+ or executable == dexec
+ or (realpath and compare_executable(realpath, desktop_entry)))
-def compare_cmdline(cmdline, de):
- dcmdline = de.get_commandline()
- ret = os.path.basename(cmdline) == os.path.basename(dcmdline) or cmdline == dcmdline
+def compare_cmdline(cmdline, desktop_entry):
+ dcmdline = desktop_entry.get_commandline()
+ ret = (os.path.basename(cmdline) == os.path.basename(dcmdline)
+ or cmdline == dcmdline)
# try to handle interpreters like python
if not ret:
cmdargs = filter(lambda x: x, cmdline.split(" "))
if len(cmdargs) > 1:
- ret = compare_executable(cmdargs[1], de)
+ ret = compare_executable(cmdargs[1], desktop_entry)
return ret
-def compare_component(component, de):
- dicon = de.get_icon()
+def compare_component(component, desktop_entry):
+ dicon = desktop_entry.get_icon()
if not dicon:
return False
@@ -81,11 +86,11 @@ def compare_component(component, de):
return component in dicon.get_names()
elif isinstance(dicon, Gio.FileIcon):
logging.debug("File icon: {0}".format(dicon.to_string()))
- bf = os.path.basename(dicon.to_string())
- if component == bf:
+ base_name = os.path.basename(dicon.to_string())
+ if component == base_name:
return True
- elif '.' in bf:
- component == bf[:bf.rindex('.')]
+ elif '.' in base_name:
+ return component == base_name[:base_name.rindex('.')]
else:
return False
else:
@@ -94,39 +99,41 @@ def compare_component(component, de):
return False
def find_application(component, executable, cmdline):
- global __globa_app_cache__
+ lookupnames = [(cmdline, compare_cmdline),
+ (executable, compare_executable),
+ (component, compare_component)]
- lookupnames = [(cmdline, compare_cmdline), (executable, compare_executable), (component, compare_component)]
-
- for n in lookupnames:
- if not n[0]:
+ for pred in lookupnames:
+ if not pred[0]:
continue
- if n[0] in __globa_app_cache__:
- return __globa_app_cache__[n[0]]
+ if pred[0] in __globa_app_cache__:
+ return __globa_app_cache__[pred[0]]
theme = Gtk.IconTheme.get_default()
for dai in Gio.DesktopAppInfo.get_all():
- if n[1](n[0], dai):
+ if pred[1](pred[0], dai):
icon = None
dai_icon = dai.get_icon()
if dai_icon:
if isinstance(dai_icon, Gio.ThemedIcon):
for name in dai_icon.get_names():
try:
- icon = theme.load_icon(name, 128, Gtk.IconLookupFlags.USE_BUILTIN)
+ icon = theme.load_icon(name,
+ 128, Gtk.IconLookupFlags.USE_BUILTIN)
break
- except gi._glib.GError as e:
- logging.debug(e.message)
+ except gi._glib.GError as ex:
+ logging.debug(ex.message)
elif isinstance(dai_icon, Gio.FileIcon):
stream = dai_icon.load(128, None)
icon = GdkPixbuf.Pixbuf.new_from_stream(stream[0], None)
else:
- logging.debug("Unsupported type of icon class: {0}".format(dai_icon))
+ logging.debug("Unsupported type of icon class: {0}"
+ .format(dai_icon))
- __globa_app_cache__[n[0]] = Application(executable,
+ __globa_app_cache__[pred[0]] = Application(executable,
name=dai.get_name(),
icon=icon)
- return __globa_app_cache__[n[0]]
+ return __globa_app_cache__[pred[0]]
return Application(executable if executable else "??")
diff --git a/src/gnome_abrt/config.py b/src/gnome_abrt/config.py
index 8213c38..0506b78 100644
--- a/src/gnome_abrt/config.py
+++ b/src/gnome_abrt/config.py
@@ -39,7 +39,7 @@ class Configuration(object):
def __getitem__(self, option):
return self.options[option].value
-
+
def __setitem__(self, option, value):
opt = self.options[option]
@@ -48,23 +48,33 @@ class Configuration(object):
opt.value = value
map(lambda o: o.option_updated(self, option), opt.observers)
+ def __delitem__(self, option):
+ pass
+
+ def __len__(self):
+ return len(self.options)
+
def get_option_value(self, option, default):
if option in self.options:
return self.options[option].value
return default
- def add_option(self, short_key, long_key=None, description=None, default_value=None):
+ def add_option(self, short_key,
+ long_key=None, description=None, default_value=None):
+
if short_key in self.options:
raise KeyError("The option already exists")
- option = collections.namedtuple('Option', 'long_key description value observers')
+ option = collections.namedtuple('Option',
+ 'long_key description value observers')
+
option.long_key = long_key
option.description = description
option.value = default_value
option.observers = []
self.options[short_key] = option
-
+
def get_configuration():
return Configuration()
diff --git a/src/gnome_abrt/controller.py.in b/src/gnome_abrt/controller.py.in
index 81aed2c..f3898ac 100644
--- a/src/gnome_abrt/controller.py.in
+++ b/src/gnome_abrt/controller.py.in
@@ -26,12 +26,13 @@ class Controller(object):
self.source = source
self.run_event_fn = self._first_event_run
+ #pylint: disable=W0613
def _handle_signal(self, signum):
while True:
try:
os.wait3(os.WNOHANG)
- except OSError as e:
- logging.debug(e.message)
+ except OSError as ex:
+ logging.debug(ex.message)
break
self.source.refresh()
@@ -58,7 +59,8 @@ class Controller(object):
self.run_event_fn("open-gui", problem)
def _first_event_run(self, event, problem):
- signal.signal(signal.SIGCHLD, lambda signum, frame: self._handle_signal(signum))
+ signal.signal(signal.SIGCHLD,
+ lambda signum, frame: self._handle_signal(signum))
self.run_event_fn = self._run_event_on_problem
self.run_event_fn(event, problem)
@@ -66,9 +68,12 @@ class Controller(object):
def _run_event_on_problem(self, event, problem):
if problem.assure_ownership():
if os.fork() == 0:
+ exctbl = "@libexecdir@/abrt-handle-event"
+ args = [exctbl, "-e", event, "--", problem.problem_id]
try:
- os.execvp("@libexecdir@/abrt-handle-event", ["@libexecdir@/abrt-handle-event", "-e", event, "--", problem.problem_id])
- except Exception as e:
- logging.exception(e)
+ os.execvp(exctbl, args)
+ #pylint: disable=W0703
+ except Exception as ex:
+ logging.exception(ex)
sys.exit(1)
diff --git a/src/gnome_abrt/dbus_problems.py b/src/gnome_abrt/dbus_problems.py
index 9aaece7..2b5a09d 100644
--- a/src/gnome_abrt/dbus_problems.py
+++ b/src/gnome_abrt/dbus_problems.py
@@ -21,10 +21,10 @@ from dbus.mainloop.glib import DBusGMainLoop
import logging
-import problems
-import config
-import errors
-from l10n import _
+import gnome_abrt.problems as problems
+import gnome_abrt.config as config
+import gnome_abrt.errors as errors
+from gnome_abrt.l10n import _
BUS_NAME = 'org.freedesktop.problems'
BUS_PATH = '/org/freedesktop/problems'
@@ -42,81 +42,102 @@ class DBusProblemSource(problems.CachedSource):
if not self._mainloop:
self._mainloop = DBusGMainLoop()
+ self._bus = None
+ self._proxy = None
+ self._interface = None
self._connect_to_problems_bus()
try:
- self.bus.add_signal_receiver(self._on_new_problem, signal_name=ABRTD_DBUS_SIGNAL,
- path=ABRTD_DBUS_PATH)
- except dbus.exceptions.DBusException as e:
- logging.warning(_("Can't add receiver of signal '{0}'on DBus system path '{1}': {2}")
- .format(ABRTD_DBUS_SIGNAL, ABRTD_DBUS_PATH, e.message))
+ self._bus.add_signal_receiver(self._on_new_problem,
+ signal_name=ABRTD_DBUS_SIGNAL, path=ABRTD_DBUS_PATH)
+ except dbus.exceptions.DBusException as ex:
+ logging.warning(
+ _("Can't add receiver of signal '{0}'on DBus system path '{1}': {2}")
+ .format(ABRTD_DBUS_SIGNAL, ABRTD_DBUS_PATH, ex.message))
class ConfigObserver():
def __init__(self, source):
self.source = source
+ #pylint: disable=W0613
def option_updated(self, conf, option):
if option == "all_problems":
self.source.refresh()
conf = config.get_configuration()
conf.set_watch("all_problems", ConfigObserver(self))
- self._all_problems = None
def _connect_to_problems_bus(self):
# I can't find any description of raised exceptions
- self.bus = dbus.SystemBus(private=True, mainloop=self._mainloop)
+ self._bus = dbus.SystemBus(private=True, mainloop=self._mainloop)
try:
- self.proxy = self.bus.get_object(BUS_NAME, BUS_PATH)
- except dbus.exceptions.DBusException as e:
- raise errors.UnavailableSource(_("Can't connect to DBus system bus '{0}' path '{1}': {2}").format(BUS_NAME, BUS_PATH, e.message))
+ self._proxy = self._bus.get_object(BUS_NAME, BUS_PATH)
+ except dbus.exceptions.DBusException as ex:
+ raise errors.UnavailableSource(
+ _("Can't connect to DBus system bus '{0}' path '{1}': {2}")
+ .format(BUS_NAME, BUS_PATH, ex.message))
try:
- self.interface = dbus.Interface(self.proxy, BUS_IFACE)
- except dbus.exceptions.DBusException as e:
- raise errors.UnavailableSource(_("Can't get interface '{0}' on path '{1}' in bus '{2}': {3}").format(BUS_IFACE, BUS_PATH, BUS_NAME, e.message))
+ self._interface = dbus.Interface(self._proxy, BUS_IFACE)
+ except dbus.exceptions.DBusException as ex:
+ raise errors.UnavailableSource(
+ _("Can't get interface '{0}' on path '{1}' in bus '{2}': {3}")
+ .format(BUS_IFACE, BUS_PATH, BUS_NAME, ex.message))
def _close_problems_bus(self):
- self.proxy = None
- self.interface = None
- self.bus.close()
- self.bus = None
+ self._proxy = None
+ self._interface = None
+ self._bus.close()
+ self._bus = None
def _send_dbus_message(self, method, *args):
try:
- return method(self.interface, *args)
- except dbus.exceptions.DBusException as e:
- if e.get_dbus_name() == "org.freedesktop.DBus.Error.ServiceUnknown":
- logging.debug("Reconnecting to dbus: {0}".format(e.message))
+ return method(self._interface, *args)
+ except dbus.exceptions.DBusException as ex:
+ name = ex.get_dbus_name()
+ if name == "org.freedesktop.DBus.Error.ServiceUnknown":
+ logging.debug("Reconnecting to dbus: {0}".format(ex.message))
self._close_problems_bus()
self._connect_to_problems_bus()
- return method(self.interface, *args)
+ return method(self._interface, *args)
raise
def _on_new_problem(self, *args):
if len(args) < 2:
- logging.debug("Received the new problem signal with invalid number of arguments {0}".format(args))
+ logging.debug(
+ "Received the new problem signal with invalid number of arguments {0}"
+ .format(args))
return
conf = config.get_configuration()
- if len(args) > 2 and int(args[2]) != os.getuid() and not conf['all_problems']:
- logging.debug("Received the new problem signal with different uid '{0}' ('{1}') and the all problems option is not configured".format(args[2], os.getuid()))
+ if (len(args) > 2
+ and int(args[2]) != os.getuid()
+ and not conf['all_problems']):
+ logging.debug("Received the new problem signal with different uid "
+ "'{0}' ('{1}') and the all problems option is not configured"
+ .format(args[2], os.getuid()))
return
if len(args) == 2 and not conf['all_problems']:
- logging.debug("Received the new problem signal without the uid argument and the all problems option is not configured")
+ logging.debug("Received the new problem signal without the uid "
+ "argument and the all problems option is not configured")
return
self.process_new_problem_id(str(args[1]))
def chown_problem(self, problem_id):
try:
- self._send_dbus_message(lambda iface, *params: iface.ChownProblemDir(*params), problem_id)
+ self._send_dbus_message(
+ #pylint: disable=W0142
+ lambda iface, *params: iface.ChownProblemDir(*params),
+ problem_id)
return True
- except dbus.exceptions.DBusException as e:
- logging.warning(_("Can't chown problem '{0}' over DBus service: {1!s}").format(problem_id, e.message))
+ except dbus.exceptions.DBusException as ex:
+ logging.warning(
+ _("Can't chown problem '{0}' over DBus service: {1!s}")
+ .format(problem_id, ex.message))
return False
def get_items(self, problem_id, *args):
@@ -124,39 +145,57 @@ class DBusProblemSource(problems.CachedSource):
if len(args) != 0:
try:
- info = self._send_dbus_message(lambda iface, *params: iface.GetInfo(*params), problem_id, args)
- except dbus.exceptions.DBusException as e:
- if e.get_dbus_name() in ["org.freedesktop.problems.AuthFailure", "org.freedesktop.problems.InvalidProblemDir"]:
+ info = self._send_dbus_message(
+ #pylint: disable=W0142
+ lambda iface, *params: iface.GetInfo(*params),
+ problem_id, args)
+ except dbus.exceptions.DBusException as ex:
+ if ex.get_dbus_name() in [
+ "org.freedesktop.problems.AuthFailure",
+ "org.freedesktop.problems.InvalidProblemDir"]:
self._remove_from_cache(problem_id)
- raise errors.InvalidProblem(e.message)
+ raise errors.InvalidProblem(ex.message)
- logging.warning(_("Can't get problem data from DBus service: {0!s}").format(e.message))
+ logging.warning(
+ _("Can't get problem data from DBus service: {0!s}")
+ .format(ex.message))
return info
- def impl_get_problems(self):
+ def _get_problems(self):
conf = config.get_configuration()
prblms = []
try:
if conf['all_problems']:
- prblms = self._send_dbus_message(lambda iface, *args: iface.GetAllProblems(*args))
+ prblms = self._send_dbus_message(
+ #pylint: disable=W0142
+ lambda iface, *args: iface.GetAllProblems(*args))
else:
- prblms = self._send_dbus_message(lambda iface, *args: self.interface.GetProblems(*args))
- except dbus.exceptions.DBusException as e:
- logging.warning(_("Can't get list of problems from DBus service: {0!s}").format(e.message))
+ prblms = self._send_dbus_message(
+ #pylint: disable=W0142
+ lambda iface, *args: self._interface.GetProblems(*args))
+ except dbus.exceptions.DBusException as ex:
+ logging.warning(
+ _("Can't get list of problems from DBus service: {0!s}")
+ .format(ex.message))
return (str(pid) for pid in prblms)
- def impl_delete_problem(self, problem_id):
+ def _delete_problem(self, problem_id):
try:
- self._send_dbus_message(lambda iface, *args: iface.DeleteProblem(*args), [problem_id])
+ self._send_dbus_message(
+ #pylint: disable=W0142
+ lambda iface, *args: iface.DeleteProblem(*args), [problem_id])
return True
- except dbus.exceptions.DBusException as e:
- if e.get_dbus_name() in ["org.freedesktop.problems.AuthFailure", "org.freedesktop.problems.InvalidProblemDir"]:
+ except dbus.exceptions.DBusException as ex:
+ if ex.get_dbus_name() in ["org.freedesktop.problems.AuthFailure",
+ "org.freedesktop.problems.InvalidProblemDir"]:
self._remove_from_cache(problem_id)
- raise errors.InvalidProblem(e.message)
+ raise errors.InvalidProblem(ex.message)
- logging.warning(_("Can't delete problem over DBus service: {0!s}").format(e.message))
+ logging.warning(
+ _("Can't delete problem over DBus service: {0!s}")
+ .format(ex.message))
return False
diff --git a/src/gnome_abrt/directory_problems.py b/src/gnome_abrt/directory_problems.py
index c3a6b16..cd2b900 100644
--- a/src/gnome_abrt/directory_problems.py
+++ b/src/gnome_abrt/directory_problems.py
@@ -16,10 +16,10 @@
## Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
import os
-import sys
import logging
# pygobject
+#pylint: disable=E0611
from gi.repository import GLib
# pyinotify
@@ -30,91 +30,112 @@ from pyinotify import WatchManager, Notifier, ProcessEvent
import report
# gnome-abrt
-import problems
-import errors
-from l10n import _
+import gnome_abrt.problems as problems
+import gnome_abrt.errors as errors
+from gnome_abrt.l10n import _
class INOTIFYGlibSource(GLib.Source):
- def __new__(cls, wm, path, handler):
+ #pylint: disable=W0613
+ def __new__(cls, watch_manager, path, handler):
# ignore the rest of arguments
- return super(INOTIFYGlibSource, cls).__new__(cls)
+ return GLib.Source.__new__(cls)
- def __init__(self, wm, path, handler):
- super(INOTIFYGlibSource, self).__init__()
+ def __init__(self, watch_manager, path, handler):
+ GLib.Source.__init__(self)
- self.wm = wm
- self.handler = handler
+ self._wm = watch_manager
+ self._handler = handler
# set timeout to 0 -> don't wait
- self.notifier = Notifier(self.wm, handler, timeout=0)
- self.wdd = self.wm.add_watch(path, handler.MASK, rec=True)
+ self._notifier = Notifier(self._wm, handler, timeout=0)
+ self._wdd = self._wm.add_watch(path, handler.MASK, rec=True)
def get_handler(self):
- return self.handler
+ return self._handler
+ #pylint: disable=W0613
def prepare(self, *args):
# wait 10 milisecond before next prepare() call
- return (self.notifier.check_events(), 10)
+ return (self._notifier.check_events(), 10)
+ #pylint: disable=W0613
def check(self, *args):
# just to be sure
- return self.notifier.check_events()
+ return self._notifier.check_events()
+ #pylint: disable=W0613
def dispatch(self, *args):
- self.notifier.read_events()
- self.notifier.process_events()
+ self._notifier.read_events()
+ self._notifier.process_events()
return True
+ #pylint: disable=W0613
def finalize(self, *args):
- self.notifier.stop()
+ self._notifier.stop()
class INOTIFYProblemHandler(ProcessEvent):
- MASK = pyinotify.IN_MOVED_TO | pyinotify.IN_CLOSE_WRITE | pyinotify.IN_CREATE | pyinotify.IN_DELETE | pyinotify.IN_MOVED_FROM
+ #pylint: disable=E1101
+ MASK = (pyinotify.IN_MOVED_TO
+ #pylint: disable=E1101
+ | pyinotify.IN_CLOSE_WRITE
+ #pylint: disable=E1101
+ | pyinotify.IN_CREATE
+ #pylint: disable=E1101
+ | pyinotify.IN_DELETE
+ #pylint: disable=E1101
+ | pyinotify.IN_MOVED_FROM)
def __init__(self, problem):
super(INOTIFYProblemHandler, self).__init__()
- self.set_problem(problem)
+ self._problem = problem
def set_problem(self, problem):
- self.problem = problem
+ self._problem = problem
def _handle_event(self, event):
if event.name != '.lock':
try:
- self.problem.refresh()
- except errors.InvalidProblem as e:
- logging.debug(e.message)
- self.problem.delete()
+ self._problem.refresh()
+ except errors.InvalidProblem as ex:
+ logging.debug(ex.message)
+ self._problem.delete()
+ #pylint: disable=C0103
def process_IN_MOVED_TO(self, event):
logging.debug("IN_MOVED_TO '{0}/{1}'".format(event.path, event.name))
self._handle_event(event)
+ #pylint: disable=C0103
def process_IN_MOVED_FROM(self, event):
logging.debug("IN_MOVED_FROM '{0}/{1}'".format(event.path, event.name))
self._handle_event(event)
+ #pylint: disable=C0103
def process_IN_CLOSE_WRITE(self, event):
logging.debug("IN_CLOSE_WRITE '{0}/{1}'".format(event.path, event.name))
self._handle_event(event)
+ #pylint: disable=C0103
def process_IN_CREATE(self, event):
logging.debug("IN_CREATE '{0}/{1}'".format(event.path, event.name))
self._handle_event(event)
+ #pylint: disable=C0103
def process_IN_DELETE(self, event):
logging.debug("IN_DELETE '{0}/{1}'".format(event.path, event.name))
self._handle_event(event)
class INOTIFYSourceHandler(ProcessEvent):
+ #pylint: disable=E1101
MASK = pyinotify.IN_MOVED_TO
def __init__(self, source):
super(INOTIFYSourceHandler, self).__init__()
self.source = source
+ #pylint: disable=C0103
def process_IN_MOVED_TO(self, event):
self.source.process_new_problem_id(os.path.join(event.path, event.name))
@@ -122,7 +143,8 @@ class INOTIFYSourceHandler(ProcessEvent):
class INOTIFYWatcher:
def __init__(self, source, directory, context):
- # context is the instance variable because the source is to be used in Problems
+ # context is the instance variable because
+ # the source is to be used in Problems
self._source = source
self._directory = directory
self._context = context
@@ -133,11 +155,14 @@ class INOTIFYWatcher:
self._wm = WatchManager()
try:
- self._gsource = INOTIFYGlibSource(self._wm, self._directory, INOTIFYSourceHandler(self._source))
+ ihndlr = INOTIFYSourceHandler(self._source)
+ self._gsource = INOTIFYGlibSource(self._wm,
+ self._directory, ihndlr)
except OSError as ex:
self._disable_on_max_watches(ex, self._directory)
return
+ #pylint: disable=E1101
self._gsource.attach(self._context)
def watch_problem(self, problem):
@@ -145,17 +170,22 @@ class INOTIFYWatcher:
return
if problem.problem_id in self._problems_watcher:
- logging.debug("Updating watcher for '{0}'".format(problem.problem_id))
- self._problems_watcher[problem.problem_id].get_handler().set_problem(problem)
+ logging.debug("Updating watcher for '{0}'"
+ .format(problem.problem_id))
+ ihndlr = self._problems_watcher[problem.problem_id].get_handler()
+ ihndlr.set_problem(problem)
else:
logging.debug("Adding watcher for '{0}'".format(problem.problem_id))
pgs = None
try:
- pgs = INOTIFYGlibSource(WatchManager(), problem.problem_id, INOTIFYProblemHandler(problem))
+ ihndlr = INOTIFYProblemHandler(problem)
+ watcher = WatchManager()
+ pgs = INOTIFYGlibSource(watcher, problem.problem_id, ihndlr)
except OSError as ex:
self._disable_on_max_watches(ex, problem.problem_id)
return
+ #pylint: disable=E1101
pgs.attach(self._context)
self._problems_watcher[problem.problem_id] = pgs
@@ -169,28 +199,39 @@ class INOTIFYWatcher:
pgs.destroy()
def _disable_on_max_watches(self, ex, directory):
- self._disabled = True
- logging.debug("Could not add inotify for directory '{0}': '{1}'".format(directory, ex.message))
- logging.warning(_("You have probably reached inotify's limit on the number of watches in '{0}'. The limit can be increased by proper configuration of inotify. For more details see man inotify(7). This event causes that you will not be notified about changes in problem data happening outside of this application. This event do not affect any other functionality.").format(self._directory))
+ self._disabled = True
+ logging.debug("Could not add inotify for directory '{0}': '{1}'"
+ .format(directory, ex.message))
+ logging.warning(
+_("You have probably reached inotify's limit on the number of watches in '{0}'."
+" The limit can be increased by proper configuration of inotify. For more "
+"details see man inotify(7). This event causes that you will not be notified "
+"about changes in problem data happening outside of this application. This "
+"event do not affect any other functionality.").format(self._directory))
class NotInitializedDirectorySource():
def __init__(self, parent):
self._parent = parent
+ #pylint: disable=W0613
def get_items(self, problem_id, *args):
- logging.debug("Getting items from unitialized directory source")
- return
+ logging.debug(
+ "Getting items for problem {0} from unitialized directory source"
+ .format(problem_id))
+ return []
def get_problems(self):
return []
- def create_new_problem(self, problem_id):
- logging.debug("Creating a problem from unitialized directory source")
+ def _create_new_problem(self, problem_id):
+ logging.debug("Creating problem {0} from unitialized directory source"
+ .format(problem_id))
return problems.Problem(problem_id, self._parent)
def delete_problem(self, problem_id):
- logging.debug("Deleting problem from unitialized directory source")
+ logging.debug("Deleting problem {0} from unitialized directory source"
+ .format(problem_id))
return True
@@ -207,12 +248,13 @@ class InitializedDirectoryProblemSource():
dd = report.dd_opendir(problem_id, report.DD_OPEN_READONLY)
if not dd:
- raise errors.InvalidProblem(_("Can't open directory: '{0}'").format(problem_id))
+ raise errors.InvalidProblem(_("Can't open directory: '{0}'")
+ .format(problem_id))
items = {}
for field_name in args:
- value = dd.load_text(field_name, report.DD_FAIL_QUIETLY_ENOENT
- | report.DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE)
+ value = dd.load_text(field_name,
+ report.DD_FAIL_QUIETLY_ENOENT | report.DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE)
if value:
items[field_name] = value
@@ -234,7 +276,7 @@ class InitializedDirectoryProblemSource():
else:
logging.debug("Omitted path: '{0}'".format(problem_id))
- def create_new_problem(self, problem_id):
+ def _create_new_problem(self, problem_id):
p = problems.Problem(problem_id, self._parent)
self._watcher.watch_problem(p)
return p
@@ -242,7 +284,8 @@ class InitializedDirectoryProblemSource():
def delete_problem(self, problem_id):
dd = report.dd_opendir(problem_id)
if not dd:
- # we can safely declare problem as deleted if directory doesn't exist
+ # we can safely declare problem as deleted
+ # if directory doesn't exist
return not os.path.isdir(problem_id)
# TODO : delete over abrtd
@@ -267,7 +310,8 @@ class DirectoryProblemSource(problems.CachedSource):
if self._initialized or os.path.isdir(self._directory):
if not self._initialized:
- self._initialized = InitializedDirectoryProblemSource(self, self._directory, self._context)
+ self._initialized = InitializedDirectoryProblemSource(
+ self, self._directory, self._context)
return self._initialized
@@ -279,11 +323,11 @@ class DirectoryProblemSource(problems.CachedSource):
def get_items(self, problem_id, *args):
return self._impl().get_items(problem_id, *args)
- def create_new_problem(self, problem_id):
- return self._impl().create_new_problem(problem_id)
+ def _create_new_problem(self, problem_id):
+ return self._impl()._create_new_problem(problem_id)
- def impl_get_problems(self):
+ def _get_problems(self):
return self._impl().get_problems()
- def impl_delete_problem(self, problem_id):
+ def _delete_problem(self, problem_id):
return self._impl().delete_problem(problem_id)
diff --git a/src/gnome_abrt/l10n.py b/src/gnome_abrt/l10n.py
index edee382..f9cab81 100644
--- a/src/gnome_abrt/l10n.py
+++ b/src/gnome_abrt/l10n.py
@@ -19,16 +19,10 @@ import gettext
import locale
GETTEXT_PROGNAME = "gnome-abrt"
-PROGNAME = "gnome-abrt"
-import locale
-import gettext
-
-_ = lambda x: gettext.lgettext(x)
+_ = gettext.lgettext
-def init(progname):
- global PROGNAME
- PROGNAME = progname
+def init():
try:
locale.setlocale(locale.LC_ALL, "")
except locale.Error:
@@ -36,7 +30,8 @@ def init(progname):
os.environ['LC_ALL'] = 'C'
locale.setlocale(locale.LC_ALL, "")
- gettext.bind_textdomain_codeset(GETTEXT_PROGNAME, locale.nl_langinfo(locale.CODESET))
+ gettext.bind_textdomain_codeset(GETTEXT_PROGNAME,
+ locale.nl_langinfo(locale.CODESET))
# TODO: configurable path to the binary
gettext.bindtextdomain(GETTEXT_PROGNAME, '/usr/share/locale')
gettext.textdomain(GETTEXT_PROGNAME)
diff --git a/src/gnome_abrt/problems.py b/src/gnome_abrt/problems.py
index a8206e3..084b410 100644
--- a/src/gnome_abrt/problems.py
+++ b/src/gnome_abrt/problems.py
@@ -19,10 +19,11 @@ import datetime
import logging
# gnome-abrt
-import application
-import errors
-import problems
-from l10n import _
+from gnome_abrt.application import find_application
+from gnome_abrt.errors import (InvalidProblem,
+ UnavailableSource,
+ GnomeAbrtError)
+from gnome_abrt.l10n import _
class ProblemSource(object):
NEW_PROBLEM = 0
@@ -51,8 +52,8 @@ class ProblemSource(object):
def detach(self, observer):
try:
self._observers.remove(observer)
- except ValueError as e:
- logging.debug(e.message)
+ except ValueError as ex:
+ logging.debug(ex.message)
def notify(self, change_type=None, problem=None):
logging.debug("{0} : Notify".format(self.__class__.__name__))
@@ -94,16 +95,18 @@ class Problem:
elif isinstance(other, Problem):
return self.problem_id == other.problem_id
- raise TypeError('Not allowed type in __eq__: ' + other.__class__.__name__)
+ raise TypeError('Not allowed type in __eq__: '
+ + other.__class__.__name__)
def __loaditems__(self, *args):
if self._deleted:
- logging.debug("Accessing deleted problem '{0}'".format(self.problem_id))
+ logging.debug("Accessing deleted problem '{0}'"
+ .format(self.problem_id))
return {}
items = self.source.get_items(self.problem_id, *args)
- for k, v in items.items():
- self.data[k] = v
+ for key, value in items.items():
+ self.data[key] = value
return items
@@ -129,6 +132,15 @@ class Problem:
return None
+ def __setitem__(self):
+ raise RuntimeError("Problems are readonly")
+
+ def __delitem__(self, item):
+ raise RuntimeError("Problems are readonly")
+
+ def __len__(self):
+ return 1
+
def _get_initial_data(self, source):
return source.get_items(self.problem_id,
'component',
@@ -138,7 +150,8 @@ class Problem:
def refresh(self):
if self._deleted:
- logging.debug("Not refreshing deleted problem '{0}'".format(self.problem_id))
+ logging.debug("Not refreshing deleted problem '{0}'"
+ .format(self.problem_id))
return
logging.debug("Refreshing problem '{0}'".format(self.problem_id))
@@ -147,13 +160,15 @@ class Problem:
self.source.notify(ProblemSource.CHANGED_PROBLEM, self)
def delete(self):
+ # TODO : weird?? the assignemt can be moved
self._deleted = True
try:
self.source.delete_problem(self.problem_id)
- except errors.GnomeAbrtError as e:
- logging.warning(_("Can't delete problem '{0}': '{1}'").format(self.problem_id, e.message))
+ except GnomeAbrtError as ex:
+ logging.warning(_("Can't delete problem '{0}': '{1}'")
+ .format(self.problem_id, ex.message))
self._deleted = False
- except Exception as e:
+ except Exception as ex:
self._deleted = False
raise
@@ -161,13 +176,13 @@ class Problem:
return not self['reported_to'] is None
def assure_ownership(self):
- return self.source.chown_problem(self.problem_id);
+ return self.source.chown_problem(self.problem_id)
def get_application(self):
if not self.app:
- self.app = application.find_application(self['component'],
- self['executable'],
- self['cmdline'])
+ self.app = find_application(self['component'],
+ self['executable'],
+ self['cmdline'])
return self.app
@@ -177,58 +192,59 @@ class Problem:
if self['reported_to']:
# Most common type of line in reported_to file
# Bugzilla: URL=http://bugzilla.com/?=123456
- for l in self['reported_to'].split('\n'):
- if len(l) == 0:
+ for line in self['reported_to'].split('\n'):
+ if len(line) == 0:
continue
- p = []
- for i in xrange(0,len(l)):
- if l[i] == ':':
+ pfx = []
+ i = 0
+ for i in xrange(0, len(line)):
+ if line[i] == ':':
break
- p.append(l[i])
+ pfx.append(line[i])
- p = ''.join(p)
+ pfx = ''.join(pfx)
i += 1
- for i in xrange(i, len(l)):
- if not l[i] == ' ':
+ for i in xrange(i, len(line)):
+ if not line[i] == ' ':
break
- r = []
- for i in xrange(i, len(l)):
- if l[i] == '=':
+ typ = []
+ for i in xrange(i, len(line)):
+ if line[i] == '=':
break
- r.append(l[i])
+ typ.append(line[i])
- r = ''.join(r)
+ typ = ''.join(typ)
i += 1
self.submission.append(
- Problem.Submission(p, r, l[i:]))
+ Problem.Submission(pfx, typ, line[i:]))
return self.submission
class MultipleSources(ProblemSource):
- def __init__(self, *args):
+ def __init__(self, sources):
super(MultipleSources, self).__init__()
- if len(args) == 0:
+ if len(sources) == 0:
raise ValueError("At least one source must be passed")
- self.sources = args
+ self.sources = sources
class SourceObserver:
def __init__(self, parent):
self.parent = parent
+ #pylint: disable=W0613
def changed(self, source, change_type=None, problem=None):
self.parent.notify(change_type, problem)
- observer = SourceObserver(self)
- for s in self.sources:
- s.attach(observer)
+ for src in self.sources:
+ src.attach(SourceObserver(self))
self._disable_notify = False
@@ -237,8 +253,8 @@ class MultipleSources(ProblemSource):
def get_problems(self):
result = []
- for s in self.sources:
- result.extend(s.get_problems())
+ for src in self.sources:
+ result.extend(src.get_problems())
return result
@@ -258,13 +274,14 @@ class MultipleSources(ProblemSource):
self._disable_notify = True
try:
- for s in self.sources:
- s.refresh()
+ for src in self.sources:
+ src.refresh()
finally:
self._disable_notify = False
self.notify()
+#pylint: disable=R0921
class CachedSource(ProblemSource):
def __init__(self):
@@ -275,13 +292,13 @@ class CachedSource(ProblemSource):
def get_problems(self):
if not self._cache:
self._cache = []
- for prblmid in self.impl_get_problems():
+ for prblmid in self._get_problems():
try:
- self._cache.append(self.create_new_problem(prblmid))
- except errors.InvalidProblem as e:
- logging.warning(e.message)
- except errors.UnavailableSource as e:
- logging.warning(e.message)
+ self._cache.append(self._create_new_problem(prblmid))
+ except InvalidProblem as ex:
+ logging.warning(ex.message)
+ except UnavailableSource as ex:
+ logging.warning(ex.message)
return self._cache if self._cache else []
@@ -289,8 +306,16 @@ class CachedSource(ProblemSource):
self._cache = None
self.notify()
+ def _get_problems(self):
+ """Overwrite this function in ancestor"""
+ raise NotImplementedError("")
+
+ def _delete_problem(self, problem_id):
+ """Overwrite this function in ancestor"""
+ raise NotImplementedError("")
+
def _problem_is_in_cache(self, problem_id):
- return not self._cache is None and problem_id in self._cache
+ return self._cache is not None and problem_id in self._cache
def _insert_to_cache(self, problem):
if not self._problem_is_in_cache(problem):
@@ -305,31 +330,33 @@ class CachedSource(ProblemSource):
return p
def delete_problem(self, problem_id):
- if not self.impl_delete_problem(problem_id):
+ if not self._delete_problem(problem_id):
return
try:
- p = self._remove_from_cache(problem_id)
- if p:
- self.notify(ProblemSource.DELETED_PROBLEM, p)
+ prblm = self._remove_from_cache(problem_id)
+ if prblm:
+ self.notify(ProblemSource.DELETED_PROBLEM, prblm)
return
- except ValueError as e:
- logging.warning(_('Not found in cache but deleted: {0}'), e.message)
+ except ValueError as ex:
+ logging.warning(_('Not found in cache but deleted: {0}'),
+ ex.message)
self._cache = None
self.notify()
- def create_new_problem(self, problem_id):
- return problems.Problem(problem_id, self)
+ def _create_new_problem(self, problem_id):
+ return Problem(problem_id, self)
def process_new_problem_id(self, problem_id):
try:
if self._problem_is_in_cache(problem_id):
- p = self._cache[self._cache.index(problem_id)]
- p.refresh()
+ prblm = self._cache[self._cache.index(problem_id)]
+ prblm.refresh()
else:
- p = self.create_new_problem(problem_id)
- self._insert_to_cache(p)
- self.notify(ProblemSource.NEW_PROBLEM, p)
- except errors.UnavailableSource as e:
- logging.warning(_("Source failed on processing of '{0}': {1}").format(problem_id, e.message))
+ prblm = self._create_new_problem(problem_id)
+ self._insert_to_cache(prblm)
+ self.notify(ProblemSource.NEW_PROBLEM, prblm)
+ except UnavailableSource as ex:
+ logging.warning(_("Source failed on processing of '{0}': {1}")
+ .format(problem_id, ex.message))
diff --git a/src/gnome_abrt/tools.py b/src/gnome_abrt/tools.py
index c5c4ba9..b733e3b 100644
--- a/src/gnome_abrt/tools.py
+++ b/src/gnome_abrt/tools.py
@@ -17,10 +17,9 @@
import datetime
import calendar
-import time
import locale
-from l10n import _
+from gnome_abrt.l10n import _
def fancydate(value, base_date=None):
"""
@@ -30,25 +29,23 @@ def fancydate(value, base_date=None):
base_date = datetime.datetime.now()
old_date = value
-
if base_date < old_date:
return _('Future')
- d = base_date.date() - old_date.date()
+ tmdt = base_date.date() - old_date.date()
- if d.days == 0:
+ if tmdt.days == 0:
return old_date.time().strftime(locale.nl_langinfo(locale.T_FMT))
- elif d.days == 1:
+ elif tmdt.days == 1:
return _('Yesterday')
# this week - return a name of a day
- if d.days < base_date.isoweekday():
- # TODO test l10n
- return calendar.day_name[base_date.weekday() - d.days]
+ if tmdt.days < base_date.isoweekday():
+ return calendar.day_name[base_date.weekday() - tmdt.days]
if old_date.month == base_date.month and old_date.year == base_date.year:
# computes a number of calendar weeks (not only 7 days)
- offset = int(round((d.days - base_date.isoweekday())/7, 0)) + 1;
+ offset = int(round((tmdt.days - base_date.isoweekday())/7, 0)) + 1
name = _('week')
elif old_date.year == base_date.year:
offset = base_date.month - old_date.month
@@ -58,6 +55,6 @@ def fancydate(value, base_date=None):
name = _('year')
if offset == 1:
- return _("Last {0!s}").format(name);
+ return _("Last {0!s}").format(name)
- return _("{0:d} {1!s}s ago").format(offset, name);
+ return _("{0:d} {1!s}s ago").format(offset, name)
diff --git a/src/gnome_abrt/views.py b/src/gnome_abrt/views.py
index 5aab3d5..6d79c17 100644
--- a/src/gnome_abrt/views.py
+++ b/src/gnome_abrt/views.py
@@ -22,22 +22,27 @@ import time
import logging
import subprocess
+#pygobject
+#pylint: disable=E0611
from gi.repository import Gtk
+#pylint: disable=E0611
from gi.repository import Gdk
-import problems
-import config
-import wrappers
-from tools import fancydate
-from l10n import _, GETTEXT_PROGNAME
-import errors
+import gnome_abrt.problems as problems
+import gnome_abrt.config as config
+import gnome_abrt.wrappers as wrappers
+import gnome_abrt.errors as errors
+from gnome_abrt.tools import fancydate
+from gnome_abrt.l10n import _, GETTEXT_PROGNAME
-def problems_filter(model, it, data):
+
+def problems_filter(model, itrtr, data):
def match_pattern(pattern, problem):
def item_match(pattern, problem):
- for i in ['component', 'reason', 'executable', 'package']:
- v = problem[i]
- if v and pattern in v:
+ for i in ['component', 'reason',
+ 'executable', 'package']:
+ val = problem[i]
+ if val and pattern in val:
return True
return (item_match(pattern, problem)
@@ -49,7 +54,7 @@ def problems_filter(model, it, data):
if len(pattern) == 0:
return True
- return match_pattern(pattern, model[it][2])
+ return match_pattern(pattern, model[itrtr][2])
class ProblemsFilter:
@@ -66,48 +71,112 @@ class ProblemsFilter:
self.current_pattern = pattern
self.tm_filter.refilter()
- it = self.view.get_model().get_iter_first()
- if it:
- self.window._select_problem_iter(it)
-
-
-# default on None :)
-def doN(text, default_text):
- if text:
- return text
- return default_text
+ itrtr = self.view.get_model().get_iter_first()
+ if itrtr:
+ self.window._select_problem_iter(itrtr)
def problem_to_storage_values(problem):
# not localizable, it is a format for tree view column
app = problem.get_application()
- return ["{0!s}\n{1!s}".format(doN(app.name, _("N/A")), doN(problem['type'], "")),
- "{0!s}\n{1!s}".format(fancydate(problem['date']), problem['count']),
+ return ["{0!s}\n{1!s}".format(app.name or _("N/A"),
+ problem['type'] or ""),
+ "{0!s}\n{1!s}".format(fancydate(problem['date']),
+ problem['count']),
problem]
-def time_sort_func(model, first, second, data):
- return time.mktime(model[first][2]['date'].timetuple()) - time.mktime(model[second][2]['date'].timetuple())
+#pylint: disable=W0613
+def time_sort_func(model, first, second, unused):
+ lhs = model[first][2]['date'].timetuple()
+ rhs = model[second][2]['date'].timetuple()
+ return time.mktime(lhs) - time.mktime(rhs)
+#pylint: disable=R0902
class OopsWindow(Gtk.ApplicationWindow):
+ class OopsGtkBuilder(object):
+ def __init__(self):
+ builder = Gtk.Builder()
+ self._builder = builder
+ builder.set_translation_domain(GETTEXT_PROGNAME)
+
+ if os.path.exists('oops.glade'):
+ builder.add_from_file(filename='oops.glade')
+ else:
+ from gnome_abrt import gnome_abrt_glade
+ builder.add_from_string(
+ gnome_abrt_glade.GNOME_ABRT_GLADE_CONTENTS)
+
+ self.wnd_main = builder.get_object('wnd_main')
+ self.gr_main_layout = builder.get_object('gr_main_layout')
+ self.ls_problems = builder.get_object('ls_problems')
+ self.lbl_reason = builder.get_object('lbl_reason')
+ self.lbl_summary = builder.get_object('lbl_summary')
+ self.lbl_app_name_value = builder.get_object('lbl_app_name_value')
+ self.lbl_app_version_value = builder.get_object(
+ 'lbl_app_version_value')
+ self.lbl_reported_value = builder.get_object('lbl_reported_value')
+ self.tv_problems = builder.get_object('tv_problems')
+ self.tvs_problems = builder.get_object('tvs_problems')
+ self.img_app_icon = builder.get_object('img_app_icon')
+ self.nb_problem_layout = builder.get_object('nb_problem_layout')
+ self.btn_delete = builder.get_object('btn_delete')
+ self.btn_report = builder.get_object('btn_report')
+ self.te_search = builder.get_object('te_search')
+ self.chb_all_problems = builder.get_object('chb_all_problems')
+ self.vbx_links = builder.get_object('vbx_links')
+ self.vbx_problem_messages = builder.get_object(
+ 'vbx_problem_messages')
+ self.gac_report = builder.get_object('gac_report')
+ self.gac_delete = builder.get_object('gac_delete')
+ self.gac_open_directory = builder.get_object('gac_open_directory')
+ self.gac_copy_id = builder.get_object('gac_copy_id')
+ self.menu_problem_item = builder.get_object('menu_problem_item')
+ self.ag_accelerators = builder.get_object('ag_accelerators')
+
+ def connect_signals(self, implementor):
+ self._builder.connect_signals(implementor)
+
+ def __getattr__(self, name):
+ obj = self._builder.get_object(name)
+
+ if obj is None:
+ raise AttributeError("Builder has not member '{0}'"
+ .format(name))
+
+ return obj
+
def __init__(self, application, source, controller):
- super(OopsWindow, self).__init__(title=_('Automatic Bug Reporting Tool'), application=application)
+ Gtk.ApplicationWindow.__init__(self,
+ title=_('Automatic Bug Reporting Tool'),
+ application=application)
- if os.path.exists('oops.glade'):
- self._load_widgets_from_builder(filename='oops.glade')
- else:
- import gnome_abrt_glade
- self._load_widgets_from_builder(content=gnome_abrt_glade.GNOME_ABRT_GLADE_CONTENTS)
+ self._builder = OopsWindow.OopsGtkBuilder()
+ self.set_default_size(*self._builder.wnd_main.get_size())
+ self._builder.wnd_main.remove(self._builder.gr_main_layout)
+ #pylint: disable=E1101
+ self.add(self._builder.gr_main_layout)
+
+ # move accelators group from the design window to this window
+ self.add_accel_group(self._builder.ag_accelerators)
+
+ css_prv = Gtk.CssProvider()
+ css_prv.load_from_data("GtkViewport {\n"
+ " background-color : @theme_bg_color;\n"
+ "}\n")
+ stl_ctx = self.get_style_context()
+ stl_ctx.add_provider_for_screen(stl_ctx.get_screen(), css_prv, 6000)
+ self._builder.connect_signals(self)
self.selected_problem = None
self._source = source
self._reloading = False
self._controller = controller
- self.ls_problems.set_sort_column_id(0,Gtk.SortType.DESCENDING)
- self.ls_problems.set_sort_func(0, time_sort_func, None)
- self._filter = ProblemsFilter(self, self.tv_problems)
+ self._builder.ls_problems.set_sort_column_id(0, Gtk.SortType.DESCENDING)
+ self._builder.ls_problems.set_sort_func(0, time_sort_func, None)
+ self._filter = ProblemsFilter(self, self._builder.tv_problems)
class SourceObserver:
def __init__(self, wnd):
@@ -127,7 +196,7 @@ class OopsWindow(Gtk.ApplicationWindow):
self._source_observer = SourceObserver(self)
self._source.attach(self._source_observer)
- self.tv_problems.grab_focus()
+ self._builder.tv_problems.grab_focus()
self._reload_problems(self._source)
class OptionsObserver:
@@ -144,58 +213,6 @@ class OopsWindow(Gtk.ApplicationWindow):
self._options_observer.option_updated(conf, 'problemid')
- def _load_widgets_from_builder(self, filename=None, content=None):
- builder = Gtk.Builder()
- builder.set_translation_domain(GETTEXT_PROGNAME)
-
- if filename:
- builder.add_from_file(filename)
- elif content:
- builder.add_from_string(content)
- else:
- raise ValueError("One of the arguments must be set")
-
- self.gr_main_layout = builder.get_object('gr_main_layout')
- wnd = builder.get_object('wnd_main')
- self.set_default_size(*wnd.get_size())
- wnd.remove(self.gr_main_layout)
- self.add(self.gr_main_layout)
-
- self.ls_problems = builder.get_object('ls_problems')
- self.lbl_reason = builder.get_object('lbl_reason')
- self.lbl_summary = builder.get_object('lbl_summary')
- self.lbl_app_name_value = builder.get_object('lbl_app_name_value')
- self.lbl_app_version_value = builder.get_object('lbl_app_version_value')
- self.lbl_reported_value = builder.get_object('lbl_reported_value')
- self.tv_problems = builder.get_object('tv_problems')
- self.tvs_problems = builder.get_object('tvs_problems')
- self.img_app_icon = builder.get_object('img_app_icon')
- self.nb_problem_layout = builder.get_object('nb_problem_layout')
- self.btn_delete = builder.get_object('btn_delete')
- self.btn_report = builder.get_object('btn_report')
- self.te_search = builder.get_object('te_search')
- self.chb_all_problems = builder.get_object('chb_all_problems')
- self.vbx_links = builder.get_object('vbx_links')
- self.vbx_problem_messages = builder.get_object('vbx_problem_messages')
- self.gac_report = builder.get_object('gac_report')
- self.gac_delete = builder.get_object('gac_delete')
- self.gac_open_directory = builder.get_object('gac_open_directory')
- self.gac_copy_id = builder.get_object('gac_copy_id')
- self.menu_problem_item = builder.get_object('menu_problem_item')
-
- # move accelators group from the design window to this window
- self.ag_accelerators = builder.get_object('ag_accelerators')
- self.add_accel_group(self.ag_accelerators)
-
- css_prv = Gtk.CssProvider()
- css_prv.load_from_data("GtkViewport {\n"
- " background-color : @theme_bg_color;\n"
- "}\n")
- stl_ctx = self.get_style_context()
- stl_ctx.add_provider_for_screen(stl_ctx.get_screen(), css_prv, 6000)
-
- builder.connect_signals(self)
-
def _find_problem_iter(self, problem, model):
pit = model.get_iter_first()
while pit:
@@ -207,88 +224,94 @@ class OopsWindow(Gtk.ApplicationWindow):
def _add_problem_to_storage(self, problem):
try:
- self.ls_problems.append(problem_to_storage_values(problem))
+ self._builder.ls_problems.append(problem_to_storage_values(problem))
except errors.InvalidProblem as ex:
logging.debug(ex.message)
def _remove_problem_from_storage(self, problem):
- pit = self._find_problem_iter(problem, self.ls_problems)
+ pit = self._find_problem_iter(problem, self._builder.ls_problems)
if pit:
- self.ls_problems.remove(pit)
+ self._builder.ls_problems.remove(pit)
def _update_problem_in_storage(self, problem):
- pit = self._find_problem_iter(problem, self.ls_problems)
+ pit = self._find_problem_iter(problem, self._builder.ls_problems)
if pit:
try:
values = problem_to_storage_values(problem)
for i in xrange(0, len(values)-1):
- self.ls_problems.set_value(pit, i, values[i])
+ self._builder.ls_problems.set_value(pit, i, values[i])
except errors.InvalidProblem as ex:
self._remove_problem_from_storage(problem)
logging.debug(ex.message)
return
- if problem == self._get_selected(self.tvs_problems):
+ if problem in self._get_selected(self._builder.tvs_problems):
self._set_problem(problem)
def _reload_problems(self, source):
self._reloading = True
- old = self._get_selected(self.tvs_problems);
+ old_selection = self._get_selected(self._builder.tvs_problems)
+ prblms = None
try:
- self.ls_problems.clear()
- problems = source.get_problems()
- for p in problems:
+ self._builder.ls_problems.clear()
+ prblms = source.get_problems()
+ for p in prblms:
self._add_problem_to_storage(p)
finally:
self._reloading = False
- if len(problems) > 0:
- if old:
- pit = self._find_problem_iter(old, self.tv_problems.get_model())
+ if prblms:
+ if old_selection:
+ pit = self._find_problem_iter(old_selection[0],
+ self._builder.tv_problems.get_model())
if pit:
self._select_problem_iter(pit)
return
- self._select_problem_iter(self.tv_problems.get_model().get_iter_first())
+ model = self._builder.tv_problems.get_model()
+ self._select_problem_iter(model.get_iter_first())
else:
self._set_problem(None)
def _select_problem_by_id(self, problem_id):
- pit = self._find_problem_iter(problem_id, self.tv_problems.get_model())
+ pit = self._find_problem_iter(problem_id,
+ self._builder.tv_problems.get_model())
if pit:
self._select_problem_iter(pit)
else:
- logging.debug("Can't select problem id '{0}' because the id was not found".format(problem_id))
+ logging.debug("Can't select problem id '{0}' because the id was "
+ "not found".format(problem_id))
def _select_problem_iter(self, pit):
- self._reloading = True
- self.tvs_problems.unselect_all()
- self._reloading = False
- path = self.tv_problems.get_model().get_path(pit)
- if not path:
- logging.debug("Can't select problem because the passed iter can't be converted to a tree path");
+ self._reloading = True
+ self._builder.tvs_problems.unselect_all()
+ self._reloading = False
+ path = self._builder.tv_problems.get_model().get_path(pit)
+ if not path:
+ logging.debug("Can't select problem because the passed iter can't"
+ " be converted to a tree path")
return
- self.tvs_problems.select_iter(pit)
- self.tv_problems.scroll_to_cell(path)
+ self._builder.tvs_problems.select_iter(pit)
+ self._builder.tv_problems.scroll_to_cell(path)
def _show_problem_links(self, submissions):
need_align = False
- for s in submissions:
- if problems.Problem.Submission.URL == s.rtype:
- lnk = Gtk.LinkButton(s.data, s.title)
+ for sbm in submissions:
+ if problems.Problem.Submission.URL == sbm.rtype:
+ lnk = Gtk.LinkButton(sbm.data, sbm.title)
lnk.set_visible(True)
lnk.set_halign(Gtk.Align.START)
lnk.set_valign(Gtk.Align.START)
- self.vbx_links.pack_start(lnk, False, True, 0)
+ self._builder.vbx_links.pack_start(lnk, False, True, 0)
need_align = True
if need_align:
space = Gtk.Alignment()
space.set_visible(True)
space.set_vexpand(True)
- self.vbx_links.pack_start(space, False, True, 0)
+ self._builder.vbx_links.pack_start(space, False, True, 0)
def _show_problem_message(self, message):
msg = Gtk.Label()
@@ -298,58 +321,60 @@ class OopsWindow(Gtk.ApplicationWindow):
msg.set_valign(Gtk.Align.START)
msg.set_line_wrap(True)
- self.vbx_problem_messages.pack_start(msg, False, True, 0)
+ self._builder.vbx_problem_messages.pack_start(msg, False, True, 0)
def _set_problem(self, problem):
try:
self.selected_problem = problem
- sensitive_btn = not problem is None
- self.btn_delete.set_sensitive(sensitive_btn)
- self.btn_report.set_sensitive(not problem is None and not problem['not-reportable'] )
- self.vbx_links.foreach(lambda w, u: w.destroy(), None)
- self.vbx_problem_messages.foreach(lambda w, u: w.destroy(), None)
+ sensitive_btn = problem is not None
+ self._builder.btn_delete.set_sensitive(sensitive_btn)
+ self._builder.btn_report.set_sensitive(
+ sensitive_btn and not problem['not-reportable'] )
+ self._builder.vbx_links.foreach(
+ lambda w, u: w.destroy(), None)
+ self._builder.vbx_problem_messages.foreach(
+ lambda w, u: w.destroy(), None)
if problem:
- self.nb_problem_layout.set_current_page(0)
+ self._builder.nb_problem_layout.set_current_page(0)
app = problem['application']
- self.lbl_reason.set_text("{0} {1}".format(doN(app.name, _("N/A")), _(' crashed').strip()));
- self.lbl_summary.set_text(doN(problem['reason'], ""))
- self.lbl_app_name_value.set_text(doN(app.name, _("N/A")))
- self.lbl_app_version_value.set_text(doN(problem['package'], ""))
+ self._builder.lbl_summary.set_text(problem['reason'] or "")
+ self._builder.lbl_app_name_value.set_text(app.name or _("N/A"))
+ self._builder.lbl_reason.set_text("{0} {1}".format(
+ app.name or _("N/A"), _(' crashed').strip()))
+ self._builder.lbl_app_version_value.set_text(
+ problem['package'] or "")
if app.icon:
- self.img_app_icon.set_from_pixbuf(app.icon)
+ self._builder.img_app_icon.set_from_pixbuf(app.icon)
else:
- self.img_app_icon.clear()
+ self._builder.img_app_icon.clear()
if problem['is_reported']:
- self.lbl_reported_value.set_text(_('yes'))
+ self._builder.lbl_reported_value.set_text(_('yes'))
self._show_problem_links(problem['submission'])
else:
- self.lbl_reported_value.set_text(_('no'))
+ self._builder.lbl_reported_value.set_text(_('no'))
if problem['not-reportable']:
self._show_problem_message(problem['not-reportable'])
- elif not problem['is_reported'] or not any((s.title == "Bugzilla" for s in problem['submission'])):
- self._show_problem_message(_("This problem hasn't been reported to <i>Bugzilla</i> yet,"\
- "our developers maybe need more information to sort out the problem.\n"\
- "Please consider <b>reporting it</b>, you may help them. Thank you."))
+ elif (not problem['is_reported']
+ or not any((s.title == "Bugzilla"
+ for s in problem['submission']))):
+ self._show_problem_message(
+ _("This problem hasn't been reported to <i>Bugzilla</i> yet,"
+ "our developers maybe need more information to sort out the problem.\n"
+ "Please consider <b>reporting it</b>, you may help them. Thank you."))
else:
- self.nb_problem_layout.set_current_page(1)
+ self._builder.nb_problem_layout.set_current_page(1)
except errors.InvalidProblem as ex:
logging.debug(ex.message)
self._source.refresh()
- def _get_selected(self, selection, only_first=True):
+ def _get_selected(self, selection):
model, rows = selection.get_selected_rows()
- if only_first:
- if not rows:
- return None
-
- return model[rows[0]][2]
-
if not rows:
return []
@@ -357,60 +382,65 @@ class OopsWindow(Gtk.ApplicationWindow):
def on_tvs_problems_changed(self, selection):
if not self._reloading:
- p = self._get_selected(selection)
- if p:
- self._set_problem(p)
+ selection = self._get_selected(selection)
+ if selection:
+ self._set_problem(selection[0])
return
- pit = self.tv_problems.get_model().get_iter_first()
+ pit = self._builder.tv_problems.get_model().get_iter_first()
if pit:
- self._select_problem_iter(pit);
+ self._select_problem_iter(pit)
return
# Clear window because of empty list of problems!
self._set_problem(None)
def on_gac_delete_activate(self, action):
- for p in self._get_selected(self.tvs_problems, False):
- self._controller.delete(p)
+ for prblm in self._get_selected(self._builder.tvs_problems):
+ self._controller.delete(prblm)
def on_gac_detail_activate(self, action):
- selected = self._get_selected(self.tvs_problems)
+ selected = self._get_selected(self._builder.tvs_problems)
if selected:
- self._controller.detail(selected)
+ self._controller.detail(selected[0])
def on_gac_report_activate(self, action):
- selected = self._get_selected(self.tvs_problems)
- if selected and not selected['not-reportable']:
- self._controller.report(selected)
+ selected = self._get_selected(self._builder.tvs_problems)
+ if selected and not selected[0]['not-reportable']:
+ self._controller.report(selected[0])
def on_te_search_changed(self, entry):
self._filter.set_pattern(entry.get_text())
def on_gac_opt_all_problems_activate(self, action):
conf = config.get_configuration()
- conf['all_problems'] = self.chb_all_problems.get_active()
+ conf['all_problems'] = self._builder.chb_all_problems.get_active()
def on_gac_control_preferences_activate(self, action):
wrappers.show_events_list_dialog(self)
def on_gac_open_directory_activate(self, action):
- p = self._get_selected(self.tvs_problems)
- if p:
- subprocess.call(["xdg-open", p.problem_id])
- self.menu_problem_item.popdown()
+ selection = self._get_selected(self._builder.tvs_problems)
+ if selection:
+ subprocess.call(["xdg-open", selection[0].problem_id])
+ self._builder.menu_problem_item.popdown()
def on_gac_copy_id_activate(self, action):
- p = self._get_selected(self.tvs_problems)
- if p:
- Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD).set_text(p.problem_id, -1)
- self.menu_problem_item.popdown()
-
- def on_tv_problems_button_press_event(self, sender, e):
- # getattribute() used because number as first character in name is syntax error
- if e.type == type.__getattribute__(Gdk.EventType, '2BUTTON_PRESS') and e.button == Gdk.BUTTON_PRIMARY:
- self.gac_report.activate()
- elif e.type == Gdk.EventType.BUTTON_PRESS and e.button == Gdk.BUTTON_SECONDARY:
- pos = self.tv_problems.get_path_at_pos(e.x, e.y)
+ selection = self._get_selected(self._builder.tvs_problems)
+ if selection:
+ (Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
+ .set_text(selection[0].problem_id, -1))
+ self._builder.menu_problem_item.popdown()
+
+ def on_tv_problems_button_press_event(self, sender, data):
+ # getattribute() used because number as first character in name
+ # is syntax error
+ if (data.type == type.__getattribute__(Gdk.EventType, '2BUTTON_PRESS')
+ and data.button == Gdk.BUTTON_PRIMARY):
+ self._builder.gac_report.activate()
+ elif (data.type == Gdk.EventType.BUTTON_PRESS
+ and data.button == Gdk.BUTTON_SECONDARY):
+ pos = self._builder.tv_problems.get_path_at_pos(data.x, data.y)
if pos:
- self.menu_problem_item.popup(None, None, None, None, e.button, e.time)
+ self._builder.menu_problem_item.popup(None, None, None, None,
+ data.button, data.time)
diff --git a/src/gnome_abrt/wrappers/Makefile.am b/src/gnome_abrt/wrappers/Makefile.am
index b2c71df..638d9b1 100644
--- a/src/gnome_abrt/wrappers/Makefile.am
+++ b/src/gnome_abrt/wrappers/Makefile.am
@@ -24,3 +24,11 @@ _wrappers_la_LDFLAGS = \
-module \
-avoid-version \
-export-symbols-regex init_wrappers
+
+_wrappers.so: $(wrappersexec_LTLIBRARIES)
+ cp .libs/$@ ./
+
+all-local: _wrappers.so
+
+clean-local:
+ rm -rf _wrappers.so
diff --git a/src/gnome_abrt/wrappers/__init__.py b/src/gnome_abrt/wrappers/__init__.py
index 3ddd821..f6a9a05 100644
--- a/src/gnome_abrt/wrappers/__init__.py
+++ b/src/gnome_abrt/wrappers/__init__.py
@@ -15,4 +15,4 @@
## along with this program; if not, write to the Free Software
## Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
-from _wrappers import show_events_list_dialog
+from gnome_abrt.wrappers._wrappers import show_events_list_dialog
--
1.8.1.4
11 years, 1 month
[PATCH] retrace-client: do not allow space in os_release_id; closes #625
by Michal Toman
---
src/plugins/abrt-retrace-client.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/plugins/abrt-retrace-client.c b/src/plugins/abrt-retrace-client.c
index 0e17a62..781a815 100644
--- a/src/plugins/abrt-retrace-client.c
+++ b/src/plugins/abrt-retrace-client.c
@@ -324,6 +324,9 @@ static char *get_release_id(const char *rawrelease, const char *architecture)
}
char *release = NULL, *version = NULL, *result = NULL;
parse_release_for_rhts(rawrelease, &release, &version);
+ char *space = strchr(version, ' ');
+ if (space)
+ *space = '\0';
if (strcmp("Fedora", release) == 0)
result = xasprintf("fedora-%s-%s", version, arch);
--
1.8.1.4
11 years, 1 month
[ABRT PATCH 1/2] Remove smolt-related parts of specfile
by Denys Vlasenko
Smolts.org is being retired by Fedora Infrastructure.
Signed-off-by: Denys Vlasenko <dvlasenk(a)redhat.com>
---
abrt.spec.in | 2 --
1 file changed, 2 deletions(-)
diff --git a/abrt.spec.in b/abrt.spec.in
index 359b15c..dc408fa 100644
--- a/abrt.spec.in
+++ b/abrt.spec.in
@@ -501,7 +501,6 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
%config(noreplace) %{_sysconfdir}/%{name}/gpg_keys
%config(noreplace) %{_sysconfdir}/libreport/events.d/abrt_event.conf
%config(noreplace) %{_sysconfdir}/libreport/events.d/smart_event.conf
-%config(noreplace) %{_sysconfdir}/libreport/events.d/smolt_event.conf
%dir %attr(0755, abrt, abrt) %{_localstatedir}/%{var_base_dir}/%{name}
%dir %attr(0700, abrt, abrt) %{_localstatedir}/spool/%{name}-upload
# abrtd runs as root
@@ -586,7 +585,6 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
%{_sysconfdir}/libreport/events/analyze_CCpp.xml
%{_sysconfdir}/libreport/events/analyze_LocalGDB.xml
%{_sysconfdir}/libreport/events/collect_xsession_errors.xml
-%{_sysconfdir}/libreport/events/collect_Smolt.xml
%{_sysconfdir}/libreport/events/collect_GConf.xml
%{_sysconfdir}/libreport/events/collect_vimrc_user.xml
%{_sysconfdir}/libreport/events/collect_vimrc_system.xml
--
1.8.1.4
11 years, 1 month
[LIBREPORT PATCH] Add test for is_text_file
by Denys Vlasenko
Signed-off-by: Denys Vlasenko <dvlasenk(a)redhat.com>
---
tests/Makefile.am | 1 +
tests/is_text_file.at | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
tests/testsuite.at | 1 +
3 files changed, 51 insertions(+)
create mode 100644 tests/is_text_file.at
diff --git a/tests/Makefile.am b/tests/Makefile.am
index dc17663..a19f1cb 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -29,6 +29,7 @@ TESTSUITE_AT = \
testsuite.at \
strbuf.at \
osrelease.at \
+ is_text_file.at \
taghyperlinks.at
EXTRA_DIST += $(TESTSUITE_AT)
diff --git a/tests/is_text_file.at b/tests/is_text_file.at
new file mode 100644
index 0000000..0a3add5
--- /dev/null
+++ b/tests/is_text_file.at
@@ -0,0 +1,49 @@
+# -*- Autotest -*-
+
+AT_BANNER([is_text_file])
+
+## ---------------------- ##
+## is_text_file ##
+## ---------------------- ##
+
+AT_TESTFUN([is_text_file],
+[[
+#include "internal_libreport.h"
+#include <assert.h>
+int main(void)
+{
+ char *dir = mkdtemp(strdup("/tmp/ddXXXXXX"));
+ assert(dir);
+ assert(chdir(dir) == 0);
+ struct dump_dir *dd = dd_create("test", -1, -1);
+ assert(dd);
+ dd_save_text(dd, "time", "12345678");
+
+ dd_save_text(dd, "os_release", "Fedora release 19 (Schrödinger's Cat)");
+ //dd_save_text(dd, "cat", "Schrödinger's Cat");
+
+ problem_data_t *problem_data = problem_data_new();
+ problem_data_load_from_dump_dir(problem_data, dd, NULL);
+ dd_close(dd);
+
+ GList *list = g_hash_table_get_keys(problem_data);
+ list = g_list_sort(list, (GCompareFunc)strcmp);
+ GList *l = list;
+ while (l)
+ {
+ const char *key = l->data;
+ l = l->next;
+ struct problem_item *item = g_hash_table_lookup(problem_data, key);
+ assert(item);
+ printf("%s:'%s'\n", key, item->content);
+ assert(!(item->flags & CD_FLAG_BIN));
+ }
+
+ dd = dd_opendir("test", 0);
+ assert(dd);
+ dd_delete(dd);
+ assert(rmdir(dir) == 0);
+
+ return 0;
+}
+]])
diff --git a/tests/testsuite.at b/tests/testsuite.at
index 5d13168..31701a5 100644
--- a/tests/testsuite.at
+++ b/tests/testsuite.at
@@ -3,4 +3,5 @@
m4_include([strbuf.at])
m4_include([osrelease.at])
+m4_include([is_text_file.at])
m4_include([taghyperlinks.at])
--
1.8.1.4
11 years, 1 month
[ABRT PATCH 1/2] remove the abrt-gui closes #629
by Jiri Moskovcak
Signed-off-by: Jiri Moskovcak <jmoskovc(a)redhat.com>
---
configure.ac | 1 -
po/POTFILES.in | 1 -
src/Makefile.am | 2 +-
src/gui-gtk/Makefile.am | 38 --
src/gui-gtk/main.c | 1422 -----------------------------------------------
5 files changed, 1 insertion(+), 1463 deletions(-)
delete mode 100644 src/gui-gtk/Makefile.am
delete mode 100644 src/gui-gtk/main.c
diff --git a/configure.ac b/configure.ac
index 07d2f02..b04a5aa 100644
--- a/configure.ac
+++ b/configure.ac
@@ -187,7 +187,6 @@ AC_CONFIG_FILES([
src/daemon/Makefile
src/hooks/Makefile
src/applet/Makefile
- src/gui-gtk/Makefile
src/cli/Makefile
src/dbus/Makefile
src/plugins/abrt-action-install-debuginfo
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 4f070a6..c54004b 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -8,7 +8,6 @@ src/daemon/abrt-server.c
src/dbus/abrt-dbus.c
src/daemon/abrtd.c
src/daemon/abrt-handle-event.c
-src/gui-gtk/main.c
src/lib/abrt_conf.c
src/lib/hooklib.c
src/lib/problem_api.c
diff --git a/src/Makefile.am b/src/Makefile.am
index ebf2a6f..b7da68f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1 +1 @@
-SUBDIRS = include lib hooks daemon applet gui-gtk plugins cli dbus python-problem
+SUBDIRS = include lib hooks daemon applet plugins cli dbus python-problem
diff --git a/src/gui-gtk/Makefile.am b/src/gui-gtk/Makefile.am
deleted file mode 100644
index 2274a41..0000000
--- a/src/gui-gtk/Makefile.am
+++ /dev/null
@@ -1,38 +0,0 @@
-bin_PROGRAMS = abrt-gui
-
-abrt_gui_SOURCES = \
- main.c
-abrt_gui_CFLAGS = \
- -I$(srcdir)/../include \
- -I$(srcdir)/../lib \
- -I$(srcdir)/../gtk-helpers \
- -DBIN_DIR=\"$(bindir)\" \
- -DLIBEXEC_DIR=\"$(libexecdir)\" \
- -DICON_DIR=\"${datadir}/abrt/icons/hicolor/48x48/status\" \
- $(GTK_CFLAGS) \
- $(LIBREPORT_GTK_CFLAGS) \
- -D_GNU_SOURCE \
- $(GIO_CFLAGS)
-# -I/usr/include/glib-2.0
-# -I/usr/lib/glib-2.0/include
-# $(LIBNOTIFY_CFLAGS)
-# $(DBUS_GLIB_CFLAGS)
-abrt_gui_LDADD = \
- -lglib-2.0 \
- -lgthread-2.0 \
- $(GIO_LIBS) \
- $(LIBREPORT_GTK_LIBS) \
- ../lib/libabrt.la \
- $(GTK_LIBS)
-# $(LIBNOTIFY_LIBS)
-
-#test_report_SOURCES = \
-# test_report.c
-#test_report_CPPFLAGS = \
-# -I$(srcdir)/../include/report -I$(srcdir)/../include \
-# $(GLIB_CFLAGS) \
-# -D_GNU_SOURCE
-#test_report_LDADD = \
-# ../lib/libreport.la
-
-DEFS = -DLOCALEDIR=\"$(localedir)\" @DEFS@
diff --git a/src/gui-gtk/main.c b/src/gui-gtk/main.c
deleted file mode 100644
index ea0c2fa..0000000
--- a/src/gui-gtk/main.c
+++ /dev/null
@@ -1,1422 +0,0 @@
-/*
- Copyright (C) 2011 ABRT Team
- Copyright (C) 2011 RedHat inc.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-*/
-#include <gtk/gtk.h>
-#include <gdk/gdkkeysyms.h>
-#include <sys/inotify.h>
-#if HAVE_LOCALE_H
-# include <locale.h>
-#endif
-#include <libreport/internal_libreport_gtk.h>
-#include "libabrt.h"
-#include "abrt-dbus.h"
-
-#if GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION < 22
-# define GDK_KEY_Delete GDK_Delete
-# define GDK_KEY_KP_Delete GDK_KP_Delete
-#endif
-
-/* We used to work with problem dirs directly.
- * Access via dbus was added in order to be able to see
- * (after authorization) problem dirs which are readable
- * only by root. These "root only" problems can also be deleted,
- * or chown'ed and then events can be run on them.
- * (IMO this feature added too much PITA for a rather limited gain.
- * Oh well...)
- */
-
-static void rescan_and_refresh(void);
-
-
-static const char help_uri[] =
-// For released versions, should be similar to:
-// "http://docs.fedoraproject.org/en-US/Fedora/14/html/Deployment_Guide/ch-ab...";
-//
-// This doc (hopefully) matches the most recent code.
-// It is supposed to be kept updated (see doc/deployment/*)
-// and uploaded to fedorahosted.org:
-"https://fedorahosted.org/releases/a/b/abrt/Deployment_Guide.html";
-
-enum {
- OPT_v = 1 << 0,
- OPT_p = 1 << 1,
- OPT_D = 1 << 2,
-};
-
-static unsigned g_opts;
-
-static int inotify_fd = -1;
-static GIOChannel *channel_inotify;
-static int channel_inotify_event_id = -1;
-static char **s_dirs;
-static int s_signal_pipe[2];
-
-static GtkListStore *s_dumps_list_store;
-static GtkListStore *s_reported_dumps_list_store;
-
-static GtkWidget *s_treeview;
-static GtkWidget *s_reported_treeview;
-static GtkWidget *s_active_treeview;
-static GtkTreePath *s_path_treeview;
-static GtkTreePath *s_path_reported_treeview;
-
-static GtkWidget *g_main_window;
-
-enum
-{
- COLUMN_SOURCE,
- COLUMN_REASON,
- COLUMN_LATEST_CRASH_STR,
- COLUMN_LATEST_CRASH,
- COLUMN_DUMP_DIR,
- COLUMN_DIR_OVER_DBUS,
- COLUMN_REPORTED_TO,
- NUM_COLUMNS
-};
-/* Must match the above enum! Used in gtk_list_store_new() call */
-# define COLUMN_TYPES \
- G_TYPE_STRING, \
- G_TYPE_STRING, \
- G_TYPE_STRING, \
- G_TYPE_INT, \
- G_TYPE_STRING, \
- G_TYPE_INT, \
- G_TYPE_STRING \
-
-/* Whether to try to authorize when getting list of problems */
-static gint g_authorize;
-
-/* Returns malloced copy */
-static char *get_last_line(const char *msg)
-{
- const char *last_eol = strrchr(msg, '\n');
-
- if (!last_eol) /* entire msg is one line? */
- return xstrdup(msg);
-
- if (last_eol[1] != '\0') /* last line is not \n terminated? */
- return xstrdup(last_eol + 1);
-
- /* It's "... \n line \n" and we point to last "\n" */
- const char *end = last_eol;
- /* Walk back */
- while (last_eol > msg)
- {
- if (last_eol[-1] == '\n') /* We found prev "\n" */
- return xstrndup(last_eol, end - last_eol);
- last_eol--;
- }
- /* There is no prev "\n" */
- return xstrndup(last_eol, end - last_eol);
-}
-
-static void show_warning_dialog(const char *message)
-{
- GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(g_main_window),
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_WARNING,
- GTK_BUTTONS_OK, /* wizard uses GTK_BUTTONS_CLOSE instead */
- "%s", message
- );
- gtk_dialog_run(GTK_DIALOG(dialog));
- gtk_widget_destroy(dialog);
-}
-
-static void watch_this_dir(const char *dir_name)
-{
-//TODO: we probably need to remove old watches too...
- if (inotify_fd >= 0 && inotify_add_watch(inotify_fd, dir_name, 0
- // | IN_ATTRIB // Metadata changed
- // | IN_CLOSE_WRITE // File opened for writing was closed
- | IN_CREATE // File/directory created in watched directory
- | IN_DELETE // File/directory deleted from watched directory
- | IN_DELETE_SELF // Watched file/directory was itself deleted
- | IN_MODIFY // File was modified
- | IN_MOVE_SELF // Watched file/directory was itself moved
- | IN_MOVED_FROM // File moved out of watched directory
- | IN_MOVED_TO // File moved into watched directory
- ) < 0)
- {
- /* Missing .abrt/spool is ok, else complain */
- if (errno != ENOENT)
- perror_msg("inotify_add_watch failed on '%s'", dir_name);
- }
-}
-
-/* Returns non 0 if str is NULL or if str consists from white spaces */
-inline static int is_null_or_empty_string(const char *str)
-{
- return !str || skip_whitespace(str)[0] == '\0';
-}
-
-static void add_directory_to_dirlist(const char *problem_dir_path, gpointer data)
-{
- bool use_dbus = (bool)data;
- problem_data_t *pd;
- if (!use_dbus)
- {
- /* Silently ignore *any* errors, not only EACCES.
- * We saw "lock file is locked by process PID" error
- * when we raced with wizard.
- */
- int sv_logmode = logmode;
- logmode = 0;
- struct dump_dir *dd = dd_opendir(problem_dir_path, DD_OPEN_READONLY | DD_FAIL_QUIETLY_EACCES);
- logmode = sv_logmode;
- if (!dd)
- return;
-//FIXME: this is inefficient. We can instead read only selected elements, not all:
- pd = create_problem_data_from_dump_dir(dd);
- dd_close(dd);
- }
- else
- {
- pd = get_problem_data_dbus(problem_dir_path);
- if (!pd)
- return;
- }
-
- char time_buf[sizeof("YYYY-MM-DD hh:mm:ss")];
- time_buf[0] = '\0';
- const char *time_str = problem_data_get_content_or_NULL(pd, FILENAME_TIME);
- time_t t = 0;
- if (time_str && time_str[0])
- {
- t = strtol(time_str, NULL, 10); /* atoi won't work past 2038! */
- struct tm *ptm = localtime(&t);
- size_t time_len = strftime(time_buf, sizeof(time_buf)-1, "%Y-%m-%d %H:%M", ptm);
- time_buf[time_len] = '\0';
- }
-
- const char *reason = problem_data_get_content_or_NULL(pd, FILENAME_NOT_REPORTABLE);
- if (is_null_or_empty_string(reason)) /* if problem is NOT not reportable we use reason */
- {
- reason = problem_data_get_content_or_NULL(pd, FILENAME_REASON);
- if (is_null_or_empty_string(reason)) /* if we don't have reason we use 'N/A' */
- reason = "N/A";
- }
-
- /* the source of the problem:
- * - first we try to load component, as we use it on Fedora
- */
- const char *source = problem_data_get_content_or_NULL(pd, FILENAME_COMPONENT);
- if (is_null_or_empty_string(source)) /* if we don't have component, we fallback to executable */
- {
- source = problem_data_get_content_or_NULL(pd, FILENAME_EXECUTABLE);
- if (is_null_or_empty_string(source)) /* even if we don't have executable, we use 'N/A' */
- source = "N/A";
- }
-
- const char *msg = problem_data_get_content_or_NULL(pd, FILENAME_REPORTED_TO);
-
- GtkListStore *list_store = s_dumps_list_store;
- char *subm_status = NULL;
- if (msg)
- {
- list_store = s_reported_dumps_list_store;
- subm_status = get_last_line(msg);
- if (is_null_or_empty_string(subm_status))
- { /* the problem is reported but the submission status is not available */
- /* we have to use 'N/A' string instead of empty string */
- free(subm_status);
- subm_status = xstrdup("N/A");
- }
- }
-
- GtkTreeIter iter;
- gtk_list_store_append(list_store, &iter);
- gtk_list_store_set(list_store, &iter,
- COLUMN_SOURCE, source,
- COLUMN_REASON, reason,
- //OPTION: time format
- COLUMN_LATEST_CRASH_STR, time_buf,
- COLUMN_LATEST_CRASH, t,
- COLUMN_DUMP_DIR, problem_dir_path,
- COLUMN_DIR_OVER_DBUS, (int)use_dbus,
- COLUMN_REPORTED_TO, subm_status,
- -1);
-
- free(subm_status);
- problem_data_free(pd);
-
- VERB1 log("added: %s", problem_dir_path);
-}
-
-static void scan_directory_and_add_to_dirlist(const char *path)
-{
- DIR *dp = opendir(path);
- if (!dp)
- {
- /* We don't want to yell if, say, $HOME/.abrt/spool doesn't exist */
- //perror_msg("Can't open directory '%s'", path);
- return;
- }
-
- struct dirent *dent;
- while ((dent = readdir(dp)) != NULL)
- {
- if (dot_or_dotdot(dent->d_name))
- continue; /* skip "." and ".." */
-
- char *full_name = concat_path_file(path, dent->d_name);
- struct stat statbuf;
- if (stat(full_name, &statbuf) == 0 && S_ISDIR(statbuf.st_mode))
- add_directory_to_dirlist(full_name, /*use_dbus:*/ (void*)false);
- free(full_name);
- }
- closedir(dp);
-
- watch_this_dir(path);
-}
-
-static void query_dbus_and_add_to_dirlist(void)
-{
- GList *problem_dirs = get_problems_over_dbus(g_authorize);
-
- if (problem_dirs == ERR_PTR)
- {
- /* One way to trigger this is to temporarily rename
- * dbus socket (/var/run/dbus/system_bus_socket)
- */
- error_msg("Error in DBus communication, falling back to direct access to '%s'", g_settings_dump_location);
- scan_directory_and_add_to_dirlist(g_settings_dump_location);
- return;
- }
-
- if (problem_dirs)
- {
- g_list_foreach(problem_dirs, (GFunc)add_directory_to_dirlist, /*use_dbus:*/ (void*)true);
- list_free_with_free(problem_dirs);
- }
-
- /* HACK ALERT! We "magically know" that dbus-reported problem dirs
- * live in g_settings_dump_location.
- * Notifications on changes should be implemented to go over dbus too.
- */
- watch_this_dir(g_settings_dump_location);
-}
-
-static void scan_dirs_and_add_to_dirlist(void)
-{
- if (!(g_opts & OPT_D))
- query_dbus_and_add_to_dirlist();
-
- char **argv = s_dirs;
- while (*argv)
- scan_directory_and_add_to_dirlist(*argv++);
-}
-
-static void rescan_dirs_and_add_to_dirlist(void)
-{
- gtk_list_store_clear(s_dumps_list_store);
- gtk_list_store_clear(s_reported_dumps_list_store);
- scan_dirs_and_add_to_dirlist();
-}
-
-
-static GtkTreePath *get_cursor(void)
-{
- GtkTreeView *treeview = GTK_TREE_VIEW(s_treeview);
- GtkTreeSelection *selection = gtk_tree_view_get_selection(treeview);
- if (selection)
- {
- GtkTreeIter iter;
- GtkTreeModel *store = gtk_tree_view_get_model(treeview);
- if (gtk_tree_selection_get_selected(selection, &store, &iter) == TRUE)
- {
- return gtk_tree_model_get_path(store, &iter);
- }
- }
- return NULL;
-}
-
-static void sanitize_cursor(GtkTreePath *preferred_path)
-{
- GtkTreePath *path;
-
- gtk_tree_view_get_cursor(GTK_TREE_VIEW(s_treeview), &path, /* GtkTreeViewColumn** */ NULL);
- if (path)
- {
- /* Cursor exists already */
- goto ret;
- }
-
- if (preferred_path)
- {
- /* Try to position cursor on preferred_path */
- gtk_tree_view_set_cursor(GTK_TREE_VIEW(s_treeview), preferred_path,
- /* GtkTreeViewColumn *focus_column */ NULL, /* start_editing */ false);
-
- /* Did it work? */
- gtk_tree_view_get_cursor(GTK_TREE_VIEW(s_treeview), &path, /* GtkTreeViewColumn** */ NULL);
- if (path) /* yes */
- goto ret;
- }
-
- /* Try to position cursor on 1st element */
- GtkTreeIter iter;
- if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(s_dumps_list_store), &iter))
- {
- /* We have at least one element, put cursor on it */
-
- /* Get path from iter pointing to 1st element */
- path = gtk_tree_model_get_path(GTK_TREE_MODEL(s_dumps_list_store), &iter);
-
- /* Use it to set cursor */
- gtk_tree_view_set_cursor(GTK_TREE_VIEW(s_treeview), path,
- /* GtkTreeViewColumn *focus_column */ NULL, /* start_editing */ false);
- }
- /* else we have no elements */
-
- ret:
- gtk_tree_path_free(path);
-
- /* Without this, the *header* of the list gets the focus. Ugly. */
- gtk_widget_grab_focus(s_treeview);
-}
-
-
-/* create_main_window and helpers */
-
-static void deactivate_selection(GtkTreeView *tv)
-{
- if (!GTK_IS_TREE_VIEW(tv))
- return;
-
- GtkTreeSelection *selection = gtk_tree_view_get_selection(tv);
- if (selection)
- {
- /* Remember the selection */
- GList *list = gtk_tree_selection_get_selected_rows(selection, /*GtkTreeModel **model:*/ NULL);
- /* Note: returned list is a copy! We take ownership (IOW: must free it) */
- GtkTreePath **pp_path = NULL;
- if ((void*)tv == (void*)s_treeview)
- pp_path = &s_path_treeview;
- if ((void*)tv == (void*)s_reported_treeview)
- pp_path = &s_path_reported_treeview;
- if (pp_path && list)
- {
- if (*pp_path)
- gtk_tree_path_free(*pp_path);
- *pp_path = list->data;
- list = g_list_delete_link(list, list);
- }
- g_list_foreach(list, (GFunc) gtk_tree_path_free, NULL);
- g_list_free(list);
- /* Deactivate */
- gtk_tree_selection_unselect_all(selection);
- }
-}
-
-/* Contrary to what I expected, this callback is NOT called
- * when I select a row with a mouse.
- * Maybe this callback can be removed.
- */
-static gboolean on_select_cursor_row_cb(
- GtkTreeView *treeview,
- gboolean arg1,
- gpointer user_data)
-{
- //log("SELECT_ROW:%p/%p", treeview, user_data);
- if (GTK_IS_TREE_VIEW(user_data))
- deactivate_selection(GTK_TREE_VIEW(user_data));
-
- return false; /* propagate the event further */
-}
-
-/* Called when I select a row with a mouse (among other cases).
- * Make sure other tv loses its selection.
- */
-static gboolean on_cursor_changed_cb(
- GtkTreeView *treeview,
- gpointer user_data)
-{
- //log("cursor-changed:%p/%p", treeview, user_data);
- if (GTK_IS_TREE_VIEW(user_data))
- deactivate_selection(GTK_TREE_VIEW(user_data));
-
- /* Without this, only <tab>ing to treeview sets s_active_treeview.
- * Thus, selecting a row with mouse and clicking [Open] with mouse
- * wouldn't work!
- */
- s_active_treeview = GTK_WIDGET(treeview);
-
- return false; /* propagate the event further */
-}
-
-/* Called when I <tab> to the treeview
- * Make sure other tv loses its selection.
- * Also, restore selection in current tv if it was desecleted
- * (for example, if we <tab>ed to the other seletion a few sec ago...).
- */
-static gboolean on_focus_cb(
- GtkWidget *widget,
- GtkDirectionType direction,
- gpointer user_data)
-{
- //log("FOCUS:%p/%p", widget, user_data);
- s_active_treeview = widget;
-
- /* Deactivate the other one */
- deactivate_selection(GTK_TREE_VIEW(user_data));
-
- /* Re-activate row in this one if it was deactivated */
- GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
- if (selection && gtk_tree_selection_count_selected_rows(selection) < 1)
- {
- GtkTreePath **pp_path = NULL;
- if (widget == s_treeview)
- pp_path = &s_path_treeview;
- if (widget == s_reported_treeview)
- pp_path = &s_path_reported_treeview;
- if (pp_path && *pp_path)
- {
- gtk_tree_selection_select_path(selection, *pp_path);
- gtk_tree_path_free(*pp_path);
- *pp_path = NULL;
- }
- }
-
- return false; /* propagate the event further */
-}
-
-static const char *current_dirname(int *is_dbus, GtkTreePath **path_p, GtkTreeView *treeview)
-{
- GtkTreeSelection *selection = gtk_tree_view_get_selection(treeview);
- if (selection)
- {
- GtkTreeIter iter;
- GtkTreeModel *store = gtk_tree_view_get_model(treeview);
- if (gtk_tree_selection_get_selected(selection, &store, &iter) == TRUE)
- {
- if (path_p)
- *path_p = gtk_tree_model_get_path(store, &iter);
-
- GValue d_dir = { 0 };
- gtk_tree_model_get_value(store, &iter, COLUMN_DUMP_DIR, &d_dir);
- const char *dirname = g_value_get_string(&d_dir);
- if (is_dbus)
- {
- GValue d_int = { 0 };
- gtk_tree_model_get_value(store, &iter, COLUMN_DIR_OVER_DBUS, &d_int);
- *is_dbus = g_value_get_int(&d_int);
- }
- return dirname;
- }
- }
- return NULL;
-}
-
-static void on_row_activated_cb(GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *column, gpointer user_data)
-{
- int is_dbus;
- const char *dirname = current_dirname(&is_dbus, NULL, treeview);
- if (dirname)
- {
- if (!is_dbus || chown_dir_over_dbus(dirname) == 0)
- {
- fflush(NULL); /* paranoia */
- pid_t pid = fork();
- if (pid < 0) /* error */
- perror_msg_and_die("fork");
- if (pid == 0) /* child */
- {
- execl(LIBEXEC_DIR"/abrt-handle-event", "abrt-handle-event", "-e", "report-gui", "--", (char *)dirname, NULL);
- /* Child can't use GUI error reporting, we need to clear g_custom_logger */
- g_custom_logger = NULL;
- perror_msg_and_die("Can't execute '%s'", LIBEXEC_DIR"/abrt-handle-event");
- }
- }
- /* else: chown_dir_over_dbus already complained */
- }
-}
-
-static void open_problem_data_cb(GtkMenuItem *menuitem, gpointer user_data)
-{
- int is_dbus;
- const char *dirname = current_dirname(&is_dbus, NULL, GTK_TREE_VIEW(s_active_treeview));
- if (dirname)
- {
- if (is_dbus && chown_dir_over_dbus(dirname) != 0)
- {
- error_msg("Can't chown '%s'", dirname);
- return;
- }
-
- fflush(NULL); /* paranoia */
- pid_t pid = fork();
- if (pid < 0) /* error */
- perror_msg_and_die("fork");
- if (pid == 0) /* child */
- {
- execl(LIBEXEC_DIR"/abrt-handle-event", "abrt-handle-event", "-e", "open-gui", "--", (char *)dirname, NULL);
- /* Child can't use GUI error reporting, we need to clear g_custom_logger */
- g_custom_logger = NULL;
- perror_msg_and_die("Can't execute '%s'", LIBEXEC_DIR"/abrt-handle-event");
- }
- }
-}
-
-static void on_btn_report_cb(GtkButton *button, gpointer user_data)
-{
- if (s_active_treeview)
- on_row_activated_cb(GTK_TREE_VIEW(s_active_treeview), NULL, NULL, NULL);
-}
-
-static void on_column_change_cb(GtkTreeSortable *sortable, gpointer user_data)
-{
- const char *name;
- char *value;
- GtkSortType sort_type;
- int col_id;
-
- if (sortable == GTK_TREE_SORTABLE(s_dumps_list_store))
- name = "sort_column";
- else if (sortable == GTK_TREE_SORTABLE(s_reported_dumps_list_store))
- name = "sort_reported_column";
- else
- assert(0);
-
- gtk_tree_sortable_get_sort_column_id(sortable, &col_id, &sort_type);
- if (sort_type == GTK_SORT_ASCENDING)
- col_id = -col_id - 1; /* store ascending sort as negative id */
- value = xasprintf("%d", col_id);
- set_user_setting(name, value);
- free(value);
-}
-
-static void on_show_all_cb(GtkToggleButton *togglebutton, gpointer data)
-{
- g_authorize = gtk_toggle_button_get_active(togglebutton);
- rescan_and_refresh();
-}
-
-static void load_sort_setting(GtkTreeSortable *sortable)
-{
- const char *name, *value;
- GtkSortType sort_type;
- int col_id;
-
- if (sortable == GTK_TREE_SORTABLE(s_dumps_list_store))
- name = "sort_column";
- else if (sortable == GTK_TREE_SORTABLE(s_reported_dumps_list_store))
- name = "sort_reported_column";
- else
- return;
-
- /* defaults */
- col_id = COLUMN_LATEST_CRASH;
- sort_type = GTK_SORT_DESCENDING;
-
- value = get_user_setting(name);
- if (value)
- {
- col_id = xatoi(value);
- if (col_id < 0)
- {
- /* negative id means ascending order */
- col_id = -col_id - 1;
- sort_type = GTK_SORT_ASCENDING;
- }
- }
-
- if (col_id >= NUM_COLUMNS)
- col_id = COLUMN_LATEST_CRASH;
-
- gtk_tree_sortable_set_sort_column_id(sortable, col_id, sort_type);
-}
-
-static void delete_problem(GtkTreeView *treeview)
-{
- GtkTreePath *old_path = NULL;
- int is_dbus;
- const char *dirname = current_dirname(&is_dbus, &old_path, GTK_TREE_VIEW(s_active_treeview));
- if (dirname)
- {
- VERB1 log("Deleting '%s'", dirname);
-
- //TODO: I plan to implement deleting multiple items at once rhbz#541928
- GList *problem_dir_paths = NULL;
- problem_dir_paths = g_list_append(problem_dir_paths, xstrdup(dirname));
-
- int result;
- if (is_dbus)
- {
- result = delete_problem_dirs_over_dbus(problem_dir_paths);
- }
- else
- {
- result = delete_dump_dir_possibly_using_abrtd(dirname);
- }
- list_free_with_free(problem_dir_paths);
-
- if (result != 0)
- {
- /* Strange. Deletion did not succeed. Someone else deleted it?
- * Rescan the whole list */
- rescan_dirs_and_add_to_dirlist();
- }
-
- /* Try to retain the same cursor position */
- if (old_path)
- {
- sanitize_cursor(old_path);
- gtk_tree_path_free(old_path);
- }
- }
-}
-
-static gint on_key_press_event_cb(GtkTreeView *treeview, GdkEventKey *key, gpointer unused)
-{
- int k = key->keyval;
-
- if (k == GDK_KEY_Delete || k == GDK_KEY_KP_Delete)
- {
- delete_problem(treeview);
- return TRUE;
- }
- return FALSE;
-}
-
-static void on_btn_delete_cb(GtkButton *button, gpointer unused)
-{
- if (s_active_treeview)
- delete_problem(GTK_TREE_VIEW(s_active_treeview));
-}
-
-static void on_menu_help_cb(GtkMenuItem *menuitem, gpointer unused)
-{
- gtk_show_uri(NULL, help_uri, GDK_CURRENT_TIME, NULL);
-}
-
-static void show_error_dialog(GtkWindow *wnd, const char *summary, const char *description)
-{
- GtkWidget *dialog = gtk_message_dialog_new(wnd,
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR,
- GTK_BUTTONS_OK,
- summary);
-
- gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), description);
-
- gtk_dialog_run(GTK_DIALOG(dialog));
- gtk_widget_destroy (dialog);
-}
-
-static void on_button_send_cb(GtkWidget *button, gpointer data)
-{
- GtkWidget *wnd_report = GTK_WIDGET(data);
-
- /* Excpecting that the first child is Vertical Box with all the widgets */
- GList *children = gtk_container_get_children(GTK_CONTAINER(wnd_report));
- GtkContainer *vbox = GTK_CONTAINER(children->data);
- g_list_free(children);
-
- /* Expected content of the children list:
- * Lable Summary
- * Entry Summary
- * TextView Description
- * Button Send
- */
- children = gtk_container_get_children(vbox);
-
- children = g_list_delete_link(children, children);
- GtkEntry *txe_summary = GTK_ENTRY(children->data);
-
- children = g_list_delete_link(children, children);
- GtkTextView *tev = GTK_TEXT_VIEW(children->data);
-
- g_list_free(children);
-
- GtkTextBuffer *buf = gtk_text_view_get_buffer(tev);
- GtkTextIter it_start;
- GtkTextIter it_end;
- gtk_text_buffer_get_start_iter(buf, &it_start);
- gtk_text_buffer_get_end_iter(buf, &it_end);
- gchar *description = gtk_text_buffer_get_text(buf,
- &it_start,
- &it_end,
- false);
-
- if (strlen(description) < 10)
- {
- show_error_dialog(GTK_WINDOW(wnd_report),
- _("The description of problem is too short"),
- _("In order to get more useful reports we "
- "do not accept reports with the description "
- "shorter than 10 letters."));
-
- gtk_widget_grab_focus(GTK_WIDGET(tev));
-
- free(description);
- return;
- }
-
- char *summary = xstrdup(gtk_entry_get_text(txe_summary));
- if (strlen(summary) < 10)
- {
- show_error_dialog(GTK_WINDOW(wnd_report),
- _("The summary of problem is too short"),
- _("In order to get more useful reports we "
- "do not accept reports with the summary "
- "shorter than 10 letters."));
-
- gtk_widget_grab_focus(GTK_WIDGET(txe_summary));
- gtk_editable_set_position(GTK_EDITABLE(txe_summary), strlen(summary));
-
- free(description);
- free(summary);
- return;
- }
-
-
- problem_data_t *pd = problem_data_new();
- problem_data_add_text_noteditable(pd, FILENAME_COMMENT, description);
- problem_data_add_text_noteditable(pd, FILENAME_REASON, summary);
- problem_data_add_text_noteditable(pd, FILENAME_COMPONENT, "abrt");
- char *version = xasprintf("abrt-%s", VERSION);
- problem_data_add_text_noteditable(pd, FILENAME_PACKAGE, version);
-
- /* Must be here because it computes FILENAME_DUPHASH from the content. */
- problem_data_add_basics(pd);
-
- /* why it doesn't want to hide before report ends? */
- gtk_widget_destroy(wnd_report);
-
- report_problem_in_memory(pd, LIBREPORT_NOWAIT | LIBREPORT_GETPID);
-
- free(version);
- free(summary);
- free(description);
- problem_data_free(pd);
-}
-
-static void on_menu_report_cb(GtkMenuItem *menuitem, gpointer unused)
-{
- GtkWidget *wnd_report = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- gtk_window_set_title(GTK_WINDOW(wnd_report), _("Problem description"));
- gtk_window_set_default_size(GTK_WINDOW(wnd_report), 400, 400);
-
- GtkWidget *vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
- gtk_widget_set_margin_top(vbox, 5);
- gtk_widget_set_margin_left(vbox, 5);
- gtk_widget_set_margin_right(vbox, 5);
-
- GtkWidget *lbl_summary = GTK_WIDGET(gtk_label_new(_("Summary:")));
- gtk_widget_set_halign(lbl_summary, GTK_ALIGN_START);
- gtk_widget_set_margin_left(lbl_summary, 3);
- gtk_widget_set_margin_right(lbl_summary, 3);
-
- GtkWidget *txe_reason = GTK_WIDGET(gtk_entry_new());
-
- GtkWidget *tev = gtk_text_view_new();
- gtk_widget_set_margin_left(tev, 3);
- gtk_widget_set_margin_right(tev, 3);
- gtk_widget_set_can_focus(tev, TRUE);
-
- GtkWidget *btn_send = gtk_button_new_with_label(_("_Send"));
- gtk_button_set_use_underline(GTK_BUTTON(btn_send), TRUE);
- g_signal_connect(btn_send, "clicked", G_CALLBACK(on_button_send_cb), wnd_report);
-
- /* gtk_box_pack_start(box, widget, expand, fill, padding) */
- gtk_box_pack_start(GTK_BOX(vbox), lbl_summary, FALSE, TRUE, 3);
- gtk_box_pack_start(GTK_BOX(vbox), txe_reason, FALSE, TRUE, 3);
- gtk_box_pack_start(GTK_BOX(vbox), tev, TRUE, TRUE, 5);
- gtk_box_pack_start(GTK_BOX(vbox), btn_send, FALSE, TRUE, 3);
-
- gtk_container_add(GTK_CONTAINER(wnd_report), vbox);
-
- gtk_widget_show_all(wnd_report);
-
- /* Sets text but text is selected :) */
- gtk_entry_set_text(GTK_ENTRY(txe_reason), _("A problem with ABRT"));
- /* Unselect text in txe_entry */
- gtk_editable_set_position(GTK_EDITABLE(txe_reason), 0);
-
- /* Move focus to text view with description of problem */
- gtk_widget_grab_focus(tev);
-}
-
-static void on_menu_about_cb(GtkMenuItem *menuitem, gpointer unused)
-{
- static const char copyright_str[] = "Copyright © 2009, 2010, 2011 Red Hat, Inc";
-
- static const char license_str[] = "This program is free software; you can redistribut"
- "e it and/or modify it under the terms of the GNU General Public License "
- "as published by the Free Software Foundation; either version 2 of the Li"
- "cense, or (at your option) any later version.\n\nThis program is distrib"
- "uted in the hope that it will be useful, but WITHOUT ANY WARRANTY; witho"
- "ut even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICU"
- "LAR PURPOSE. See the GNU General Public License for more details.\n\nYo"
- "u should have received a copy of the GNU General Public License along wi"
- "th this program. If not, see <http://www.gnu.org/licenses/>.";
-
- static const char website_url[] = "https://fedorahosted.org/abrt/";
-
- static const char *authors[] = {
- "Anton Arapov <aarapov(a)redhat.com>",
- "Karel Klic <kklic(a)redhat.com>",
- "Jiri Moskovcak <jmoskovc(a)redhat.com>",
- "Nikola Pajkovsky <npajkovs(a)redhat.com>",
- "Denys Vlasenko <dvlasenk(a)redhat.com>",
- "Michal Toman <mtoman(a)redhat.com>",
- "Zdenek Prikryl",
- NULL
- };
-
- static const char *artists[] = {
- "Patrick Connelly <pcon(a)fedoraproject.org>",
- "Máirín Duffy <duffy(a)fedoraproject.org>",
- "Lapo Calamandrei",
- "Jakub Steinar <jsteiner(a)redhat.com>",
- NULL
- };
-
- GtkWidget *about_d = gtk_about_dialog_new();
-
- gtk_window_set_icon_name(GTK_WINDOW(about_d), "abrt");
- gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(about_d), VERSION);
- gtk_about_dialog_set_logo_icon_name(GTK_ABOUT_DIALOG(about_d), "abrt");
- gtk_about_dialog_set_program_name(GTK_ABOUT_DIALOG(about_d), "ABRT");
- gtk_about_dialog_set_copyright(GTK_ABOUT_DIALOG(about_d), copyright_str);
- gtk_about_dialog_set_license(GTK_ABOUT_DIALOG(about_d), license_str);
- gtk_about_dialog_set_wrap_license(GTK_ABOUT_DIALOG(about_d),true);
- gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(about_d), website_url);
- gtk_about_dialog_set_authors(GTK_ABOUT_DIALOG(about_d), authors);
- gtk_about_dialog_set_artists(GTK_ABOUT_DIALOG(about_d), artists);
- gtk_about_dialog_set_translator_credits(GTK_ABOUT_DIALOG(about_d), _("translator-credits"));
-
- gtk_window_set_transient_for(GTK_WINDOW(about_d), GTK_WINDOW(g_main_window));
-
- gtk_dialog_run(GTK_DIALOG(about_d));
- gtk_widget_hide(GTK_WIDGET(about_d));
-}
-
-static void show_events_list_dialog_cb(GtkMenuItem *menuitem, gpointer user_data)
-{
- show_config_list_dialog(GTK_WINDOW(g_main_window));
-}
-
-static void add_columns(GtkTreeView *treeview)
-{
- GtkCellRenderer *renderer;
- GtkTreeViewColumn *column;
-
- renderer = gtk_cell_renderer_text_new();
- column = gtk_tree_view_column_new_with_attributes(_("Source"),
- renderer,
- "text",
- COLUMN_SOURCE,
- NULL);
- gtk_tree_view_column_set_resizable(column, TRUE);
- gtk_tree_view_column_set_sort_column_id(column, COLUMN_SOURCE);
- gtk_tree_view_append_column(treeview, column);
-
- renderer = gtk_cell_renderer_text_new();
- column = gtk_tree_view_column_new_with_attributes(_("Problem"),
- renderer,
- "text",
- COLUMN_REASON,
- NULL);
- gtk_tree_view_column_set_resizable(column, TRUE);
- gtk_tree_view_column_set_sort_column_id(column, COLUMN_REASON);
- gtk_tree_view_append_column(treeview, column);
-
- /*
- renderer = gtk_cell_renderer_text_new();
- column = gtk_tree_view_column_new_with_attributes(_("Stored in"),
- renderer,
- "text",
- COLUMN_DIRNAME,
- NULL);
- gtk_tree_view_column_set_resizable(column, TRUE);
- gtk_tree_view_column_set_sort_column_id(column, COLUMN_DIRNAME);
- gtk_tree_view_append_column(treeview, column);
- */
- renderer = gtk_cell_renderer_text_new();
- column = gtk_tree_view_column_new_with_attributes(_("Last Occurrence"),
- renderer,
- "text",
- COLUMN_LATEST_CRASH_STR,
- NULL);
- gtk_tree_view_column_set_sort_column_id(column, COLUMN_LATEST_CRASH);
- gtk_tree_view_append_column(treeview, column);
-}
-
-static void add_columns_reported(GtkTreeView *treeview)
-{
- GtkCellRenderer *renderer;
- GtkTreeViewColumn *column;
-
- renderer = gtk_cell_renderer_text_new();
- column = gtk_tree_view_column_new_with_attributes(_("Source"),
- renderer,
- "text",
- COLUMN_SOURCE,
- NULL);
- gtk_tree_view_column_set_resizable(column, TRUE);
- gtk_tree_view_column_set_sort_column_id(column, COLUMN_SOURCE);
- gtk_tree_view_append_column(treeview, column);
-
- renderer = gtk_cell_renderer_text_new();
- column = gtk_tree_view_column_new_with_attributes(_("Problem"),
- renderer,
- "text",
- COLUMN_REASON,
- NULL);
- gtk_tree_view_column_set_resizable(column, TRUE);
- gtk_tree_view_column_set_sort_column_id(column, COLUMN_REASON);
- gtk_tree_view_append_column(treeview, column);
-
- renderer = gtk_cell_renderer_text_new();
- column = gtk_tree_view_column_new_with_attributes(_("Date Submitted"),
- renderer,
- "text",
- COLUMN_LATEST_CRASH_STR,
- NULL);
- gtk_tree_view_column_set_sort_column_id(column, COLUMN_LATEST_CRASH);
- gtk_tree_view_append_column(treeview, column);
-
- renderer = gtk_cell_renderer_text_new();
- column = gtk_tree_view_column_new_with_attributes(_("Submission Result"),
- renderer,
- "text",
- COLUMN_REPORTED_TO,
- NULL);
- //gtk_tree_view_column_set_sort_column_id(column, COLUMN_LATEST_CRASH);
- gtk_tree_view_append_column(treeview, column);
-}
-
-void on_quit_cb(GtkWidget *widget, gpointer user_data)
-{
- GApplication *app = user_data;
-
- g_application_quit(app);
-}
-
-static GtkWidget *create_menu(GtkApplication *app)
-{
- /* main bar */
- GtkWidget *menu = gtk_menu_bar_new();
- GtkWidget *file_item = gtk_menu_item_new_with_mnemonic(_("_Problem"));
- GtkWidget *edit_item = gtk_menu_item_new_with_mnemonic(_("_Edit"));
- GtkWidget *help_item = gtk_menu_item_new_with_mnemonic(_("_Help"));
-
- gtk_menu_shell_append(GTK_MENU_SHELL(menu), file_item);
- gtk_menu_shell_append(GTK_MENU_SHELL(menu), edit_item);
- gtk_menu_shell_append(GTK_MENU_SHELL(menu), help_item);
-
- /* file submenu */
- GtkWidget *file_submenu = gtk_menu_new();
- GtkWidget *quit_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_QUIT, NULL);
- GtkWidget *report_item = gtk_image_menu_item_new_with_label(_("Report"));
- g_signal_connect(report_item, "activate", G_CALLBACK(on_btn_report_cb), NULL);
- GtkWidget *open_problem_item = gtk_menu_item_new_with_label(_("Open problem data"));
- g_signal_connect(open_problem_item, "activate", G_CALLBACK(open_problem_data_cb), NULL);
-
- gtk_menu_shell_append(GTK_MENU_SHELL(file_submenu), report_item);
- gtk_menu_shell_append(GTK_MENU_SHELL(file_submenu), open_problem_item);
- gtk_menu_shell_append(GTK_MENU_SHELL(file_submenu), quit_item);
-
- gtk_menu_item_set_submenu(GTK_MENU_ITEM(file_item), file_submenu);
-
- g_signal_connect(quit_item, "activate", (GCallback)on_quit_cb, app);
-
- /* edit submenu */
- GtkWidget *edit_submenu = gtk_menu_new();
-
- GtkWidget *preferences_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_PREFERENCES, NULL);
- gtk_menu_shell_append(GTK_MENU_SHELL(edit_submenu), preferences_item);
- //gtk_menu_shell_append(GTK_MENU_SHELL(edit_submenu), preferences_item);
- gtk_menu_item_set_submenu(GTK_MENU_ITEM(edit_item), edit_submenu);
-
- g_signal_connect(preferences_item, "activate", G_CALLBACK(show_events_list_dialog_cb), NULL);
-
- /* help submenu */
- GtkWidget *help_submenu = gtk_menu_new();
- GtkWidget *online_help_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_HELP, NULL);
- GtkWidget *report_problem_item = gtk_menu_item_new_with_label(_("Report problem with ABRT"));
- GtkWidget *about_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_ABOUT, NULL);
- gtk_menu_shell_append(GTK_MENU_SHELL(help_submenu), online_help_item);
- gtk_menu_shell_append(GTK_MENU_SHELL(help_submenu), report_problem_item);
- gtk_menu_shell_append(GTK_MENU_SHELL(help_submenu), about_item);
- gtk_menu_item_set_submenu(GTK_MENU_ITEM(help_item), help_submenu);
-
- g_signal_connect(online_help_item, "activate", G_CALLBACK(on_menu_help_cb), NULL);
- g_signal_connect(report_problem_item, "activate", G_CALLBACK(on_menu_report_cb), NULL);
- g_signal_connect(about_item, "activate", G_CALLBACK(on_menu_about_cb), NULL);
-
- return menu;
-}
-
-static GtkWidget *create_main_window(GtkApplication *app)
-{
- /* Main window */
- g_main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- gtk_window_set_default_size(GTK_WINDOW(g_main_window), 700, 700);
- gtk_window_set_title(GTK_WINDOW(g_main_window), _("Automatic Bug Reporting Tool"));
- gtk_window_set_default_icon_name("abrt");
-
- GtkWidget *main_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
- /* add menu */
- gtk_box_pack_start(GTK_BOX(main_vbox), create_menu(app), false, false, 0);
-
- GtkWidget *not_subm_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
- gtk_container_set_border_width(GTK_CONTAINER(not_subm_vbox), 10);
- GtkWidget *subm_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
- gtk_container_set_border_width(GTK_CONTAINER(subm_vbox), 10);
-
- /* Scrolled region for not reported problems inside main window*/
- GtkWidget *new_problems_scroll_win = gtk_scrolled_window_new(NULL, NULL);
- gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(new_problems_scroll_win),
- GTK_SHADOW_ETCHED_IN);
- gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(new_problems_scroll_win),
- GTK_POLICY_AUTOMATIC,
- GTK_POLICY_AUTOMATIC);
-
- GtkWidget *not_subm_lbl = gtk_label_new(_("Not submitted reports"));
- gtk_misc_set_alignment(GTK_MISC(not_subm_lbl), 0, 0);
- gtk_label_set_markup(GTK_LABEL(not_subm_lbl), _("<b>Not submitted reports</b>"));
-
- GtkWidget *show_all_btn = gtk_check_button_new_with_label(_("Show all problems"));
- g_signal_connect(show_all_btn, "toggled", G_CALLBACK(on_show_all_cb), NULL);
-
- /* add label for not submitted tree view */
- gtk_box_pack_start(GTK_BOX(not_subm_vbox), not_subm_lbl, false, false, 0);
- gtk_box_pack_start(GTK_BOX(not_subm_vbox), new_problems_scroll_win, true, true, 0);
- gtk_box_pack_start(GTK_BOX(main_vbox), not_subm_vbox, true, true, 0);
- gtk_box_pack_start(GTK_BOX(main_vbox), show_all_btn, false, false, 0);
-
- /* Two tree views */
- s_treeview = gtk_tree_view_new();
- s_reported_treeview = gtk_tree_view_new();
-
- /* Tree view inside scrolled region */
- g_object_set(s_treeview, "rules-hint", 1, NULL); /* use alternating colors */
- add_columns(GTK_TREE_VIEW(s_treeview));
- gtk_container_add(GTK_CONTAINER(new_problems_scroll_win), s_treeview);
-
- /* Create data store for the list and attach it */
- s_dumps_list_store = gtk_list_store_new(NUM_COLUMNS, COLUMN_TYPES);
-
- load_sort_setting(GTK_TREE_SORTABLE(s_dumps_list_store));
-
- g_signal_connect(GTK_TREE_SORTABLE(s_dumps_list_store), "sort-column-changed", G_CALLBACK(on_column_change_cb), NULL);
-
- gtk_tree_view_set_model(GTK_TREE_VIEW(s_treeview), GTK_TREE_MODEL(s_dumps_list_store));
-
- /* Double click/Enter handler */
- g_signal_connect(s_treeview, "row-activated", G_CALLBACK(on_row_activated_cb), NULL);
- g_signal_connect(s_treeview, "focus", G_CALLBACK(on_focus_cb), s_reported_treeview);
- g_signal_connect(s_treeview, "select-cursor-row", G_CALLBACK(on_select_cursor_row_cb), s_reported_treeview);
- g_signal_connect(s_treeview, "cursor-changed", G_CALLBACK(on_cursor_changed_cb), s_reported_treeview);
- /* Delete handler */
- g_signal_connect(s_treeview, "key-press-event", G_CALLBACK(on_key_press_event_cb), NULL);
-
- /* scrolled region for reported problems */
- GtkWidget *reported_problems_scroll_win = gtk_scrolled_window_new(NULL, NULL);
- gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(reported_problems_scroll_win),
- GTK_SHADOW_ETCHED_IN);
- gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(reported_problems_scroll_win),
- GTK_POLICY_AUTOMATIC,
- GTK_POLICY_AUTOMATIC);
-
- GtkWidget *subm_lbl = gtk_label_new(_("Submitted reports"));
- /* align to left */
- gtk_misc_set_alignment(GTK_MISC(subm_lbl), 0, 0);
- gtk_label_set_markup(GTK_LABEL(subm_lbl), _("<b>Submitted reports</b>"));
-
- /* add label for submitted tree view */
- gtk_box_pack_start(GTK_BOX(subm_vbox), subm_lbl, false, false, 0);
- gtk_box_pack_start(GTK_BOX(subm_vbox), reported_problems_scroll_win, true, true, 0);
- gtk_box_pack_start(GTK_BOX(main_vbox), subm_vbox, true, true, 0);
-
- /* Tree view inside scrolled region */
- g_object_set(s_reported_treeview, "rules-hint", 1, NULL); /* use alternating colors */
- add_columns_reported(GTK_TREE_VIEW(s_reported_treeview));
- gtk_container_add(GTK_CONTAINER(reported_problems_scroll_win), s_reported_treeview);
-
- /* Create data store for the list and attach it */
- s_reported_dumps_list_store = gtk_list_store_new(NUM_COLUMNS, COLUMN_TYPES);
-
- load_sort_setting(GTK_TREE_SORTABLE(s_reported_dumps_list_store));
-
- g_signal_connect(GTK_TREE_SORTABLE(s_reported_dumps_list_store), "sort-column-changed", G_CALLBACK(on_column_change_cb), NULL);
-
- gtk_tree_view_set_model(GTK_TREE_VIEW(s_reported_treeview), GTK_TREE_MODEL(s_reported_dumps_list_store));
-
- /* buttons are homogenous so set size only for one button and it will
- * work for the rest buttons in same gtk_hbox_new() */
- GtkWidget *btn_report = gtk_button_new_with_label(_("Report"));
- gtk_widget_set_size_request(btn_report, 200, 30);
-
- GtkWidget *btn_delete = gtk_button_new_from_stock(GTK_STOCK_DELETE);
-
- GtkWidget *hbox_report_delete = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
- gtk_box_set_homogeneous(GTK_BOX(hbox_report_delete), true);
- gtk_box_pack_start(GTK_BOX(hbox_report_delete), btn_delete, true, true, 0);
- gtk_box_pack_start(GTK_BOX(hbox_report_delete), btn_report, true, true, 10);
-
- GtkWidget *halign = gtk_alignment_new(1, 0, 0, 0);
- gtk_container_add(GTK_CONTAINER(halign), hbox_report_delete);
-
- gtk_box_pack_start(GTK_BOX(main_vbox), halign, false, false, 10);
-
- /* put the main_vbox to main window */
- gtk_container_add(GTK_CONTAINER(g_main_window), main_vbox);
-
- /* Double click/Enter handler */
- g_signal_connect(s_reported_treeview, "row-activated", G_CALLBACK(on_row_activated_cb), NULL);
- g_signal_connect(s_reported_treeview, "focus", G_CALLBACK(on_focus_cb), s_treeview);
- g_signal_connect(s_reported_treeview, "select-cursor-row", G_CALLBACK(on_select_cursor_row_cb), s_treeview);
- g_signal_connect(s_reported_treeview, "cursor-changed", G_CALLBACK(on_cursor_changed_cb), s_treeview);
- /* Delete handler */
- g_signal_connect(s_reported_treeview, "key-press-event", G_CALLBACK(on_key_press_event_cb), NULL);
-
- /* Open and delete button handlers */
- g_signal_connect(btn_report, "clicked", G_CALLBACK(on_btn_report_cb), NULL);
- g_signal_connect(btn_delete, "clicked", G_CALLBACK(on_btn_delete_cb), NULL);
-
- /* Quit when user closes the main window */
- g_signal_connect(g_main_window, "destroy", (GCallback)on_quit_cb, app);
-
- return g_main_window;
-}
-
-
-static void rescan_and_refresh(void)
-{
- GtkTreePath *old_path = get_cursor();
- //log("old_path1:'%s'", gtk_tree_path_to_string(old_path)); //leak
-
- rescan_dirs_and_add_to_dirlist();
-
- /* Try to restore cursor position */
- //log("old_path2:'%s'", gtk_tree_path_to_string(old_path)); //leak
- sanitize_cursor(old_path);
- if (old_path)
- gtk_tree_path_free(old_path);
-}
-
-
-static void handle_signal(int signo)
-{
- int save_errno = errno;
-
- // Enable for debugging only, malloc/printf are unsafe in signal handlers
- //VERB3 log("Got signal %d", signo);
-
- uint8_t sig_caught = signo;
- if (write(s_signal_pipe[1], &sig_caught, 1))
- /* we ignore result, if () shuts up stupid compiler */;
-
- errno = save_errno;
-}
-
-static gboolean handle_signal_pipe(GIOChannel *gio, GIOCondition condition, gpointer ptr_unused)
-{
- /* It can only be SIGCHLD. Therefore we do not check the result,
- * and eat more than one byte at once: why refresh twice?
- */
- gchar buf[16];
- gsize bytes_read;
- g_io_channel_read_chars(gio, buf, sizeof(buf), &bytes_read, NULL);
-
- /* Destroy zombies */
- while (safe_waitpid(-1, NULL, WNOHANG) > 0)
- continue;
-
- rescan_and_refresh();
-
- return TRUE; /* "please don't remove this event" */
-}
-
-
-static gboolean handle_inotify_cb(GIOChannel *gio, GIOCondition condition, gpointer ptr_unused);
-
-static void init_notify(void)
-{
- VERB1 log("Initializing inotify");
- errno = 0;
- inotify_fd = inotify_init();
- if (inotify_fd < 0)
- perror_msg("inotify_init failed");
- else
- {
- close_on_exec_on(inotify_fd);
- ndelay_on(inotify_fd);
- VERB1 log("Adding inotify watch to glib main loop");
- channel_inotify = g_io_channel_unix_new(inotify_fd);
- channel_inotify_event_id = g_io_add_watch(channel_inotify,
- G_IO_IN,
- handle_inotify_cb,
- NULL);
- }
-}
-
-#if 0 // UNUSED
-static void close_notify(void)
-{
- if (inotify_fd >= 0)
- {
- //VERB1 log("g_source_remove:");
- g_source_remove(channel_inotify_event_id);
- //VERB1 log("g_io_channel_unref:");
- g_io_channel_unref(channel_inotify);
- //VERB1 log("close(inotify_fd):");
- close(inotify_fd);
- inotify_fd = -1;
- //VERB1 log("Done");
- }
-}
-#endif
-
-/* Inotify handler */
-static gboolean handle_inotify_cb(GIOChannel *gio, GIOCondition condition, gpointer ptr_unused)
-{
- /* Since dump dir creation usually involves directory rename as a last step,
- * we end up rescanning twice. A small wait after first inotify event
- * usually allows to avoid this.
- */
- usleep(10*1000);
-
- /* We read inotify events, but don't analyze them */
- gchar buf[sizeof(struct inotify_event) + PATH_MAX + 64];
- gsize bytes_read;
- while (g_io_channel_read_chars(gio, buf, sizeof(buf), &bytes_read, NULL) == G_IO_STATUS_NORMAL
- && bytes_read > 0
- ) {
- continue;
- }
-
- rescan_and_refresh();
-
- return TRUE; /* "please don't remove this event" */
-}
-
-static void activate(GtkApplication *app)
-{
-
- GList *windows = NULL;
-
- windows = gtk_application_get_windows(app);
-
- if (windows)
- {
- gtk_window_present(GTK_WINDOW(windows->data));
- return;
- }
-
- GtkWidget *main_window = create_main_window(app);
- load_abrt_conf();
- load_user_settings("abrt-gui");
-
- init_notify();
-
- scan_dirs_and_add_to_dirlist();
-
- gtk_window_set_application(GTK_WINDOW(main_window), app);
-
- gtk_widget_show_all(main_window);
-
- sanitize_cursor(NULL);
-
- /* Set up signal pipe */
- xpipe(s_signal_pipe);
- close_on_exec_on(s_signal_pipe[0]);
- close_on_exec_on(s_signal_pipe[1]);
- ndelay_on(s_signal_pipe[0]);
- ndelay_on(s_signal_pipe[1]);
- signal(SIGCHLD, handle_signal);
- g_io_add_watch(g_io_channel_unix_new(s_signal_pipe[0]),
- G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
- handle_signal_pipe,
- NULL);
-
- g_custom_logger = &show_warning_dialog;
-
- return;
-}
-
-int main(int argc, char **argv)
-{
- /* I18n */
- setlocale(LC_ALL, "");
-#if ENABLE_NLS
- bindtextdomain(PACKAGE, LOCALEDIR);
- textdomain(PACKAGE);
-#endif
-
- abrt_init(argv);
-
- /* without this the name is set to argv[0] which confuses
- * desktops which use the name to find the corresponding .desktop file
- * trac#180
- */
- g_set_prgname("abrt");
-
- gtk_init(&argc, &argv);
-
- /* Can't keep these strings/structs static: _() doesn't support that */
- const char *program_usage_string = _(
- "& [-vpD] [DIR]...\n"
- "\n"
- "Shows list of problem directories in specified DIR(s)\n"
- "and ones saved in system-wide problem directory spool."
- /* don't end last line with "\n"! */
- );
- /* Keep OPT_x enums and order of options below in sync! */
- struct options program_options[] = {
- OPT__VERBOSE(&g_verbose),
- OPT_BOOL( 'p', NULL, NULL , _("Add program names to log")),
- OPT_BOOL( 'D', NULL, NULL , _("Do not query problems over dbus (use only DIRs)")),
- OPT_END()
- };
- g_opts = parse_opts(argc, argv, program_options, program_usage_string);
-
- migrate_to_xdg_dirs();
-
- export_abrt_envvars(g_opts & OPT_p);
-
- const char *default_dirs[] = {
- NULL,
- NULL,
- };
- argv += optind;
- if (!argv[0])
- {
- default_dirs[0] = concat_path_file(g_get_user_cache_dir(), "abrt/spool");
- argv = (char**)default_dirs;
- }
- s_dirs = argv;
-
- GtkApplication *app = NULL;
-
-
- app = gtk_application_new("org.freedesktop.AbrtGui", 0);
- g_signal_connect(app, "activate", G_CALLBACK (activate), NULL);
- gint status;
- status = g_application_run(G_APPLICATION(app), argc, argv);
-
- g_object_unref(app);
-
- save_user_settings();
- free_abrt_conf_data();
-
- return status;
-}
--
1.8.1.4
11 years, 1 month
[PATCH] Remove all smolt-related files and code bits
by Denys Vlasenko
Smolts.org is being retired by Fedora Infrastructure.
Signed-off-by: Denys Vlasenko <dvlasenk(a)redhat.com>
---
abrt.spec.in | 2 --
doc/project/abrt.tex | 1 -
src/plugins/Makefile.am | 3 ---
src/plugins/collect_Smolt.xml.in | 10 ---------
src/plugins/smolt_event.conf | 25 ----------------------
src/python-problem/doc/properties.rst | 1 -
.../rhel6/verify-that-report-edits/expect | 9 --------
7 files changed, 51 deletions(-)
delete mode 100644 src/plugins/collect_Smolt.xml.in
delete mode 100644 src/plugins/smolt_event.conf
diff --git a/abrt.spec.in b/abrt.spec.in
index 359b15c..dc408fa 100644
--- a/abrt.spec.in
+++ b/abrt.spec.in
@@ -501,7 +501,6 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
%config(noreplace) %{_sysconfdir}/%{name}/gpg_keys
%config(noreplace) %{_sysconfdir}/libreport/events.d/abrt_event.conf
%config(noreplace) %{_sysconfdir}/libreport/events.d/smart_event.conf
-%config(noreplace) %{_sysconfdir}/libreport/events.d/smolt_event.conf
%dir %attr(0755, abrt, abrt) %{_localstatedir}/%{var_base_dir}/%{name}
%dir %attr(0700, abrt, abrt) %{_localstatedir}/spool/%{name}-upload
# abrtd runs as root
@@ -586,7 +585,6 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
%{_sysconfdir}/libreport/events/analyze_CCpp.xml
%{_sysconfdir}/libreport/events/analyze_LocalGDB.xml
%{_sysconfdir}/libreport/events/collect_xsession_errors.xml
-%{_sysconfdir}/libreport/events/collect_Smolt.xml
%{_sysconfdir}/libreport/events/collect_GConf.xml
%{_sysconfdir}/libreport/events/collect_vimrc_user.xml
%{_sysconfdir}/libreport/events/collect_vimrc_system.xml
diff --git a/doc/project/abrt.tex b/doc/project/abrt.tex
index 72a17a5..9e7724e 100644
--- a/doc/project/abrt.tex
+++ b/doc/project/abrt.tex
@@ -1537,7 +1537,6 @@ password
child[faded] {node[faded] {Dedup\-li\-ca\-tion}}
child {node {Collect RPM Data}}
child[faded] {node[faded] {Collect GConf Data}}
- child[faded] {node[faded] {Collect Smolt Data}}
child[faded] {node[faded] {Collect X Session Errors}}
child[faded] {node[faded] {Collect SMART Data}}
}
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
index 33f201d..6ace57f 100644
--- a/src/plugins/Makefile.am
+++ b/src/plugins/Makefile.am
@@ -39,7 +39,6 @@ dist_events_DATA = \
analyze_RetraceServer.xml \
analyze_VMcore.xml \
collect_xsession_errors.xml \
- collect_Smolt.xml \
collect_GConf.xml \
collect_vimrc_user.xml \
collect_vimrc_system.xml \
@@ -57,7 +56,6 @@ dist_eventsconf_DATA = \
vmcore_event.conf \
python_event.conf \
smart_event.conf \
- smolt_event.conf \
gconf_event.conf \
vimrc_event.conf
@@ -71,7 +69,6 @@ PYTHON_FILES = \
EXTRA_DIST = \
$(PYTHON_FILES) \
- collect_Smolt.xml.in \
collect_xsession_errors.xml.in \
collect_GConf.xml.in \
collect_vimrc_user.xml.in \
diff --git a/src/plugins/collect_Smolt.xml.in b/src/plugins/collect_Smolt.xml.in
deleted file mode 100644
index 63542de..0000000
--- a/src/plugins/collect_Smolt.xml.in
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<event>
- <_name>Collect Smolt profile</_name>
- <_description>Save your computer's hardware profile information</_description>
- <_long-description>
- Runs smoltSendProfile -p and saves its output as 'smolt_data' element.
- </_long-description>
- <creates-items>smolt_data</creates-items>
- <gui-review-elements>no</gui-review-elements>
-</event>
diff --git a/src/plugins/smolt_event.conf b/src/plugins/smolt_event.conf
deleted file mode 100644
index c5d4f1d..0000000
--- a/src/plugins/smolt_event.conf
+++ /dev/null
@@ -1,25 +0,0 @@
-# Rationale:
-#
-# https://bugzilla.redhat.com/show_bug.cgi?id=606123
-# Peter Hjalmarsson 2010-06-20 15:43:36 EDT
-# requested a possibility to attach the smolt profile
-# to ABRT-generated bug reports.
-# He said:
-# "When it comes to for example crashes in X drivers this is very valuable
-# information."
-#
-# To be moved to smolt package, so that it is (de)installed
-# together with these packages.
-
-EVENT=collect_Smolt
- which smoltSendProfile >/dev/null 2>&1 || {
- echo "Smolt package not installed, can't save profile"
- exit 0
- }
- if smoltSendProfile -p >smolt_data 2>&1; then
- echo "Smolt profile successfully saved"
- else
- # Don't fail because this event is executed in every reporting process
- # and smolt profile is not so important item to break reporting
- echo "Can't save smolt profile"
- fi
diff --git a/src/python-problem/doc/properties.rst b/src/python-problem/doc/properties.rst
index e5b9452..84fc8d8 100644
--- a/src/python-problem/doc/properties.rst
+++ b/src/python-problem/doc/properties.rst
@@ -72,7 +72,6 @@ Property Meaning E
``suspend_stats`` Copy of /sys/kernel/debug/suspend_stats Kerneloops
``reported_to`` If the problem was already reported, this item contains Reported problems
URLs of the services where it was reported
-``smolt_data`` Smolt profile of the machine Reported problems
``event_log`` ABRT event log Reported problems
``dmesg`` Copy of dmesg Kerneloops
===================== ======================================================== ====================================== ===============================
diff --git a/tests/runtests/distro_specific/rhel6/verify-that-report-edits/expect b/tests/runtests/distro_specific/rhel6/verify-that-report-edits/expect
index 9264683..eec33c5 100755
--- a/tests/runtests/distro_specific/rhel6/verify-that-report-edits/expect
+++ b/tests/runtests/distro_specific/rhel6/verify-that-report-edits/expect
@@ -34,15 +34,6 @@ while {1} {
"Downloading" {
send "N\r"
}
- # collectors
- -re "\n (\[0-9\]).*?Smolt" {
- puts "Got Smolt"
- set smolt_opt $expect_out(1,string)
- puts ">> $smolt_opt"
- }
- "Select collector" {
- send "$smolt_opt\r"
- }
# reporters
-re "\n (\[0-9\]).*?Bugzilla" {
puts "Got Bugzilla"
--
1.8.1.4
11 years, 1 month