mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 00:36:51 +00:00
GstDebugViewer: basic port to gtk3 and python gobject
This commit is contained in:
parent
0344fd3a49
commit
9deda12d08
17 changed files with 631 additions and 180 deletions
|
@ -19,10 +19,9 @@
|
|||
|
||||
"""GStreamer Development Utilities Common Data module."""
|
||||
|
||||
import pygtk
|
||||
pygtk.require ("2.0")
|
||||
import gi
|
||||
|
||||
import gobject
|
||||
from gi.repository import GObject
|
||||
|
||||
class Dispatcher (object):
|
||||
|
||||
|
@ -52,14 +51,14 @@ class GSourceDispatcher (Dispatcher):
|
|||
def __call__ (self, iterator):
|
||||
|
||||
if self.source_id is not None:
|
||||
gobject.source_remove (self.source_id)
|
||||
GObject.source_remove (self.source_id)
|
||||
|
||||
self.source_id = gobject.idle_add (iterator.next, priority = gobject.PRIORITY_LOW)
|
||||
self.source_id = GObject.idle_add (iterator.next, priority = GObject.PRIORITY_LOW)
|
||||
|
||||
def cancel (self):
|
||||
|
||||
if self.source_id is None:
|
||||
return
|
||||
|
||||
gobject.source_remove (self.source_id)
|
||||
GObject.source_remove (self.source_id)
|
||||
self.source_id = None
|
||||
|
|
|
@ -23,15 +23,16 @@ import os
|
|||
|
||||
import logging
|
||||
|
||||
import pygtk
|
||||
pygtk.require ("2.0")
|
||||
del pygtk
|
||||
import gi
|
||||
|
||||
import gobject
|
||||
import gtk
|
||||
from gi.repository import GObject
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import Gdk
|
||||
from gi.types import GObjectMeta
|
||||
|
||||
import GstDebugViewer
|
||||
from GstDebugViewer.Common import utils
|
||||
from generictreemodel import GenericTreeModel
|
||||
|
||||
def widget_add_popup_menu (widget, menu, button = 3):
|
||||
|
||||
|
@ -78,10 +79,10 @@ class Widgets (dict):
|
|||
def __init__ (self, builder):
|
||||
|
||||
widgets = (obj for obj in builder.get_objects ()
|
||||
if isinstance(obj, gtk.Buildable))
|
||||
# gtk.Widget.get_name() shadows out the GtkBuildable interface method
|
||||
if isinstance(obj, Gtk.Buildable))
|
||||
# Gtk.Widget.get_name() shadows out the GtkBuildable interface method
|
||||
# of the same name, hence calling the unbound interface method here:
|
||||
items = ((gtk.Buildable.get_name (w), w,) for w in widgets)
|
||||
items = ((Gtk.Buildable.get_name (w), w,) for w in widgets)
|
||||
|
||||
dict.__init__ (self, items)
|
||||
|
||||
|
@ -108,7 +109,7 @@ class WidgetFactory (object):
|
|||
|
||||
builder_filename = os.path.join (self.directory, filename)
|
||||
|
||||
builder = gtk.Builder ()
|
||||
builder = Gtk.Builder ()
|
||||
builder.set_translation_domain (GstDebugViewer.GETTEXT_DOMAIN)
|
||||
builder.add_from_file (builder_filename)
|
||||
|
||||
|
@ -141,7 +142,7 @@ class UIFactory (object):
|
|||
|
||||
def make (self, extra_actions = None):
|
||||
|
||||
ui_manager = gtk.UIManager ()
|
||||
ui_manager = Gtk.UIManager ()
|
||||
for action_group in self.action_groups.values ():
|
||||
ui_manager.insert_action_group (action_group, 0)
|
||||
if extra_actions:
|
||||
|
@ -152,7 +153,7 @@ class UIFactory (object):
|
|||
|
||||
return ui_manager
|
||||
|
||||
class MetaModel (gobject.GObjectMeta):
|
||||
class MetaModel (GObjectMeta):
|
||||
|
||||
"""Meta class for easy setup of gtk tree models.
|
||||
|
||||
|
@ -167,13 +168,13 @@ class MetaModel (gobject.GObjectMeta):
|
|||
cls.name2 = 1
|
||||
...
|
||||
|
||||
Example: A gtk.ListStore derived model can use
|
||||
Example: A Gtk.ListStore derived model can use
|
||||
|
||||
columns = ("COL_NAME", str, "COL_VALUE", str)
|
||||
|
||||
and use this in __init__:
|
||||
|
||||
gtk.ListStore.__init__ (self, *self.column_types)
|
||||
GObject.GObject.__init__ (self, *self.column_types)
|
||||
|
||||
Then insert data like this:
|
||||
|
||||
|
@ -497,10 +498,10 @@ class WindowState (object):
|
|||
|
||||
def handle_window_state_event (self, window, event):
|
||||
|
||||
if not event.changed_mask & gtk.gdk.WINDOW_STATE_MAXIMIZED:
|
||||
if not event.changed_mask & Gdk.WindowState.MAXIMIZED:
|
||||
return
|
||||
|
||||
if event.new_window_state & gtk.gdk.WINDOW_STATE_MAXIMIZED:
|
||||
if event.new_window_state & Gdk.WindowState.MAXIMIZED:
|
||||
self.logger.debug ("maximized")
|
||||
self.is_maximized = True
|
||||
else:
|
||||
|
|
|
@ -28,11 +28,10 @@ import locale
|
|||
import gettext
|
||||
from gettext import gettext as _, ngettext
|
||||
|
||||
import pygtk
|
||||
pygtk.require ("2.0")
|
||||
del pygtk
|
||||
import gi
|
||||
|
||||
import gobject
|
||||
from gi.repository import GObject
|
||||
from gi.repository import Gtk;
|
||||
|
||||
class ExceptionHandler (object):
|
||||
|
||||
|
@ -305,8 +304,8 @@ class OptionParser (object):
|
|||
|
||||
# Remaining args parsing with pygobject does not work with glib before
|
||||
# 2.13.2 (e.g. Ubuntu Feisty).
|
||||
## if gobject.glib_version >= (2, 13, 2,):
|
||||
## self.__entries.append ((gobject.OPTION_REMAINING, "\0", 0, "", "",))
|
||||
## if GObject.glib_version >= (2, 13, 2,):
|
||||
## self.__entries.append ((GObject.OPTION_REMAINING, "\0", 0, "", "",))
|
||||
|
||||
def add_option (self, long_name, short_name = None, description = None,
|
||||
arg_name = None, arg_parser = None, hidden = False):
|
||||
|
@ -321,12 +320,12 @@ class OptionParser (object):
|
|||
description = ""
|
||||
|
||||
if arg_name is None:
|
||||
flags |= gobject.OPTION_FLAG_NO_ARG
|
||||
flags |= GObject.OPTION_FLAG_NO_ARG
|
||||
elif arg_parser is not None:
|
||||
self.__parsers[long_name] = arg_parser
|
||||
|
||||
if hidden:
|
||||
flags |= gobject.OPTION_FLAG_HIDDEN
|
||||
flags |= GObject.OPTION_FLAG_HIDDEN
|
||||
|
||||
self.__entries.append ((long_name, short_name, flags, description,
|
||||
arg_name,))
|
||||
|
@ -334,7 +333,7 @@ class OptionParser (object):
|
|||
def __handle_option (self, option, arg, group):
|
||||
|
||||
# See __init__ for glib requirement.
|
||||
## if option == gobject.OPTION_REMAINING:
|
||||
## if option == GObject.OPTION_REMAINING:
|
||||
## self.__remaining_args.append (arg)
|
||||
## return
|
||||
|
||||
|
@ -356,14 +355,14 @@ class OptionParser (object):
|
|||
|
||||
def parse (self, argv):
|
||||
|
||||
context = gobject.OptionContext (self.get_parameter_string ())
|
||||
group = gobject.OptionGroup (None, None, None, self.__handle_option)
|
||||
context = GObject.OptionContext (self.get_parameter_string ())
|
||||
group = GObject.OptionGroup (None, None, None, self.__handle_option)
|
||||
context.set_main_group (group)
|
||||
group.add_entries (self.__entries)
|
||||
|
||||
try:
|
||||
result_argv = context.parse (argv)
|
||||
except gobject.GError as exc:
|
||||
except GObject.GError as exc:
|
||||
raise OptionError (exc.message)
|
||||
|
||||
self.__remaining_args = result_argv[1:]
|
||||
|
|
|
@ -20,3 +20,4 @@
|
|||
"""GStreamer Development Utilities Common package."""
|
||||
|
||||
import Data, GUI, Main, utils
|
||||
|
||||
|
|
418
debug-viewer/GstDebugViewer/Common/generictreemodel.py
Normal file
418
debug-viewer/GstDebugViewer/Common/generictreemodel.py
Normal file
|
@ -0,0 +1,418 @@
|
|||
# -*- Mode: Python; py-indent-offset: 4 -*-
|
||||
# generictreemodel - GenericTreeModel implementation for pygtk compatibility.
|
||||
# Copyright (C) 2013 Simon Feltman
|
||||
#
|
||||
# generictreemodel.py: GenericTreeModel implementation for pygtk compatibility
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
#
|
||||
# This library 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
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
# System
|
||||
import sys
|
||||
import random
|
||||
import collections
|
||||
import ctypes
|
||||
|
||||
# GObject
|
||||
from gi.repository import GObject
|
||||
from gi.repository import Gtk
|
||||
|
||||
|
||||
class _CTreeIter(ctypes.Structure):
|
||||
_fields_ = [('stamp', ctypes.c_int),
|
||||
('user_data', ctypes.c_void_p),
|
||||
('user_data2', ctypes.c_void_p),
|
||||
('user_data3', ctypes.c_void_p)]
|
||||
|
||||
@classmethod
|
||||
def from_iter(cls, iter):
|
||||
offset = sys.getsizeof(object()) # size of PyObject_HEAD
|
||||
return ctypes.POINTER(cls).from_address(id(iter) + offset)
|
||||
|
||||
|
||||
def _get_user_data_as_pyobject(iter):
|
||||
citer = _CTreeIter.from_iter(iter)
|
||||
return ctypes.cast(citer.contents.user_data, ctypes.py_object).value
|
||||
|
||||
|
||||
def handle_exception(default_return):
|
||||
"""Returns a function which can act as a decorator for wrapping exceptions and
|
||||
returning "default_return" upon an exception being thrown.
|
||||
|
||||
This is used to wrap Gtk.TreeModel "do_" method implementations so we can return
|
||||
a proper value from the override upon an exception occurring with client code
|
||||
implemented by the "on_" methods.
|
||||
"""
|
||||
def decorator(func):
|
||||
def wrapped_func(*args, **kargs):
|
||||
try:
|
||||
return func(*args, **kargs)
|
||||
except:
|
||||
# Use excepthook directly to avoid any printing to the screen
|
||||
# if someone installed an except hook.
|
||||
sys.excepthook(*sys.exc_info())
|
||||
return default_return
|
||||
return wrapped_func
|
||||
return decorator
|
||||
|
||||
|
||||
class GenericTreeModel(GObject.GObject, Gtk.TreeModel):
|
||||
"""A base implementation of a Gtk.TreeModel for python.
|
||||
|
||||
The GenericTreeModel eases implementing the Gtk.TreeModel interface in Python.
|
||||
The class can be subclassed to provide a TreeModel implementation which works
|
||||
directly with Python objects instead of iterators.
|
||||
|
||||
All of the on_* methods should be overridden by subclasses to provide the
|
||||
underlying implementation a way to access custom model data. For the purposes of
|
||||
this API, all custom model data supplied or handed back through the overridable
|
||||
API will use the argument names: node, parent, and child in regards to user data
|
||||
python objects.
|
||||
|
||||
The create_tree_iter, set_user_data, invalidate_iters, iter_is_valid methods are
|
||||
available to help manage Gtk.TreeIter objects and their Python object references.
|
||||
|
||||
GenericTreeModel manages a pool of user data nodes that have been used with iters.
|
||||
This pool stores a references to user data nodes as a dictionary value with the
|
||||
key being the integer id of the data. This id is what the Gtk.TreeIter objects
|
||||
use to reference data in the pool.
|
||||
References will be removed from the pool when the model is deleted or explicitly
|
||||
by using the optional "node" argument to the "row_deleted" method when notifying
|
||||
the model of row deletion.
|
||||
"""
|
||||
|
||||
leak_references = GObject.Property(default=True, type=bool,
|
||||
blurb="If True, strong references to user data attached to iters are "
|
||||
"stored in a dictionary pool (default). Otherwise the user data is "
|
||||
"stored as a raw pointer to a python object without a reference.")
|
||||
|
||||
#
|
||||
# Methods
|
||||
#
|
||||
def __init__(self):
|
||||
"""Initialize. Make sure to call this from derived classes if overridden."""
|
||||
super(GenericTreeModel, self).__init__()
|
||||
self.stamp = 0
|
||||
|
||||
#: Dictionary of (id(user_data): user_data), used when leak-refernces=False
|
||||
self._held_refs = dict()
|
||||
|
||||
# Set initial stamp
|
||||
self.invalidate_iters()
|
||||
|
||||
def iter_depth_first(self):
|
||||
"""Depth-first iteration of the entire TreeModel yielding the python nodes."""
|
||||
stack = collections.deque([None])
|
||||
while stack:
|
||||
it = stack.popleft()
|
||||
if it is not None:
|
||||
yield self.get_user_data(it)
|
||||
children = [self.iter_nth_child(it, i) for i in range(self.iter_n_children(it))]
|
||||
stack.extendleft(reversed(children))
|
||||
|
||||
def invalidate_iter(self, iter):
|
||||
"""Clear user data and its reference from the iter and this model."""
|
||||
iter.stamp = 0
|
||||
if iter.user_data:
|
||||
if iter.user_data in self._held_refs:
|
||||
del self._held_refs[iter.user_data]
|
||||
iter.user_data = None
|
||||
|
||||
def invalidate_iters(self):
|
||||
"""
|
||||
This method invalidates all TreeIter objects associated with this custom tree model
|
||||
and frees their locally pooled references.
|
||||
"""
|
||||
self.stamp = random.randint(-2147483648, 2147483647)
|
||||
self._held_refs.clear()
|
||||
|
||||
def iter_is_valid(self, iter):
|
||||
"""
|
||||
:Returns:
|
||||
True if the gtk.TreeIter specified by iter is valid for the custom tree model.
|
||||
"""
|
||||
return iter.stamp == self.stamp
|
||||
|
||||
def get_user_data(self, iter):
|
||||
"""Get the user_data associated with the given TreeIter.
|
||||
|
||||
GenericTreeModel stores arbitrary Python objects mapped to instances of Gtk.TreeIter.
|
||||
This method allows to retrieve the Python object held by the given iterator.
|
||||
"""
|
||||
if self.leak_references:
|
||||
return self._held_refs[iter.user_data]
|
||||
else:
|
||||
return _get_user_data_as_pyobject(iter)
|
||||
|
||||
def set_user_data(self, iter, user_data):
|
||||
"""Applies user_data and stamp to the given iter.
|
||||
|
||||
If the models "leak_references" property is set, a reference to the
|
||||
user_data is stored with the model to ensure we don't run into bad
|
||||
memory problems with the TreeIter.
|
||||
"""
|
||||
iter.user_data = id(user_data)
|
||||
|
||||
if user_data is None:
|
||||
self.invalidate_iter(iter)
|
||||
else:
|
||||
iter.stamp = self.stamp
|
||||
if self.leak_references:
|
||||
self._held_refs[iter.user_data] = user_data
|
||||
|
||||
def create_tree_iter(self, user_data):
|
||||
"""Create a Gtk.TreeIter instance with the given user_data specific for this model.
|
||||
|
||||
Use this method to create Gtk.TreeIter instance instead of directly calling
|
||||
Gtk.Treeiter(), this will ensure proper reference managment of wrapped used_data.
|
||||
"""
|
||||
iter = Gtk.TreeIter()
|
||||
self.set_user_data(iter, user_data)
|
||||
return iter
|
||||
|
||||
def _create_tree_iter(self, data):
|
||||
"""Internal creation of a (bool, TreeIter) pair for returning directly
|
||||
back to the view interfacing with this model."""
|
||||
if data is None:
|
||||
return (False, None)
|
||||
else:
|
||||
it = self.create_tree_iter(data)
|
||||
return (True, it)
|
||||
|
||||
def row_deleted(self, path, node=None):
|
||||
"""Notify the model a row has been deleted.
|
||||
|
||||
Use the node parameter to ensure the user_data reference associated
|
||||
with the path is properly freed by this model.
|
||||
|
||||
:Parameters:
|
||||
path : Gtk.TreePath
|
||||
Path to the row that has been deleted.
|
||||
node : object
|
||||
Python object used as the node returned from "on_get_iter". This is
|
||||
optional but ensures the model will not leak references to this object.
|
||||
"""
|
||||
super(GenericTreeModel, self).row_deleted(path)
|
||||
node_id = id(node)
|
||||
if node_id in self._held_refs:
|
||||
del self._held_refs[node_id]
|
||||
|
||||
#
|
||||
# GtkTreeModel Interface Implementation
|
||||
#
|
||||
@handle_exception(0)
|
||||
def do_get_flags(self):
|
||||
"""Internal method."""
|
||||
return self.on_get_flags()
|
||||
|
||||
@handle_exception(0)
|
||||
def do_get_n_columns(self):
|
||||
"""Internal method."""
|
||||
return self.on_get_n_columns()
|
||||
|
||||
@handle_exception(GObject.TYPE_INVALID)
|
||||
def do_get_column_type(self, index):
|
||||
"""Internal method."""
|
||||
return self.on_get_column_type(index)
|
||||
|
||||
@handle_exception((False, None))
|
||||
def do_get_iter(self, path):
|
||||
"""Internal method."""
|
||||
return self._create_tree_iter(self.on_get_iter(path))
|
||||
|
||||
@handle_exception(False)
|
||||
def do_iter_next(self, iter):
|
||||
"""Internal method."""
|
||||
if iter is None:
|
||||
next_data = self.on_iter_next(None)
|
||||
else:
|
||||
next_data = self.on_iter_next(self.get_user_data(iter))
|
||||
|
||||
self.set_user_data(iter, next_data)
|
||||
return next_data is not None
|
||||
|
||||
@handle_exception(None)
|
||||
def do_get_path(self, iter):
|
||||
"""Internal method."""
|
||||
path = self.on_get_path(self.get_user_data(iter))
|
||||
if path is None:
|
||||
return None
|
||||
else:
|
||||
return Gtk.TreePath(path)
|
||||
|
||||
@handle_exception(None)
|
||||
def do_get_value(self, iter, column):
|
||||
"""Internal method."""
|
||||
return self.on_get_value(self.get_user_data(iter), column)
|
||||
|
||||
@handle_exception((False, None))
|
||||
def do_iter_children(self, parent):
|
||||
"""Internal method."""
|
||||
data = self.get_user_data(parent) if parent else None
|
||||
return self._create_tree_iter(self.on_iter_children(data))
|
||||
|
||||
@handle_exception(False)
|
||||
def do_iter_has_child(self, parent):
|
||||
"""Internal method."""
|
||||
return self.on_iter_has_child(self.get_user_data(parent))
|
||||
|
||||
@handle_exception(0)
|
||||
def do_iter_n_children(self, iter):
|
||||
"""Internal method."""
|
||||
if iter is None:
|
||||
return self.on_iter_n_children(None)
|
||||
return self.on_iter_n_children(self.get_user_data(iter))
|
||||
|
||||
@handle_exception((False, None))
|
||||
def do_iter_nth_child(self, parent, n):
|
||||
"""Internal method."""
|
||||
if parent is None:
|
||||
data = self.on_iter_nth_child(None, n)
|
||||
else:
|
||||
data = self.on_iter_nth_child(self.get_user_data(parent), n)
|
||||
return self._create_tree_iter(data)
|
||||
|
||||
@handle_exception((False, None))
|
||||
def do_iter_parent(self, child):
|
||||
"""Internal method."""
|
||||
return self._create_tree_iter(self.on_iter_parent(self.get_user_data(child)))
|
||||
|
||||
@handle_exception(None)
|
||||
def do_ref_node(self, iter):
|
||||
self.on_ref_node(self.get_user_data(iter))
|
||||
|
||||
@handle_exception(None)
|
||||
def do_unref_node(self, iter):
|
||||
self.on_unref_node(self.get_user_data(iter))
|
||||
|
||||
#
|
||||
# Python Subclass Overridables
|
||||
#
|
||||
def on_get_flags(self):
|
||||
"""Overridable.
|
||||
|
||||
:Returns Gtk.TreeModelFlags:
|
||||
The flags for this model. See: Gtk.TreeModelFlags
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def on_get_n_columns(self):
|
||||
"""Overridable.
|
||||
|
||||
:Returns:
|
||||
The number of columns for this model.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def on_get_column_type(self, index):
|
||||
"""Overridable.
|
||||
|
||||
:Returns:
|
||||
The column type for the given index.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def on_get_iter(self, path):
|
||||
"""Overridable.
|
||||
|
||||
:Returns:
|
||||
A python object (node) for the given TreePath.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def on_iter_next(self, node):
|
||||
"""Overridable.
|
||||
|
||||
:Parameters:
|
||||
node : object
|
||||
Node at current level.
|
||||
|
||||
:Returns:
|
||||
A python object (node) following the given node at the current level.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def on_get_path(self, node):
|
||||
"""Overridable.
|
||||
|
||||
:Returns:
|
||||
A TreePath for the given node.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def on_get_value(self, node, column):
|
||||
"""Overridable.
|
||||
|
||||
:Parameters:
|
||||
node : object
|
||||
column : int
|
||||
Column index to get the value from.
|
||||
|
||||
:Returns:
|
||||
The value of the column for the given node."""
|
||||
raise NotImplementedError
|
||||
|
||||
def on_iter_children(self, parent):
|
||||
"""Overridable.
|
||||
|
||||
:Returns:
|
||||
The first child of parent or None if parent has no children.
|
||||
If parent is None, return the first node of the model.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def on_iter_has_child(self, node):
|
||||
"""Overridable.
|
||||
|
||||
:Returns:
|
||||
True if the given node has children.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def on_iter_n_children(self, node):
|
||||
"""Overridable.
|
||||
|
||||
:Returns:
|
||||
The number of children for the given node. If node is None,
|
||||
return the number of top level nodes.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def on_iter_nth_child(self, parent, n):
|
||||
"""Overridable.
|
||||
|
||||
:Parameters:
|
||||
parent : object
|
||||
n : int
|
||||
Index of child within parent.
|
||||
|
||||
:Returns:
|
||||
The child for the given parent index starting at 0. If parent None,
|
||||
return the top level node corresponding to "n".
|
||||
If "n" is larger then available nodes, return None.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def on_iter_parent(self, child):
|
||||
"""Overridable.
|
||||
|
||||
:Returns:
|
||||
The parent node of child or None if child is a top level node."""
|
||||
raise NotImplementedError
|
||||
|
||||
def on_ref_node(self, node):
|
||||
pass
|
||||
|
||||
def on_unref_node(self, node):
|
||||
pass
|
|
@ -23,7 +23,7 @@ import os
|
|||
import logging
|
||||
import re
|
||||
|
||||
# Nanosecond resolution (like gst.SECOND)
|
||||
# Nanosecond resolution (like Gst.SECOND)
|
||||
SECOND = 1000000000
|
||||
|
||||
def time_args (ts):
|
||||
|
|
|
@ -22,9 +22,7 @@
|
|||
__author__ = u"René Stadler <mail@renestadler.de>"
|
||||
__version__ = "0.1"
|
||||
|
||||
import pygtk
|
||||
pygtk.require ("2.0")
|
||||
del pygtk
|
||||
import gi
|
||||
|
||||
from GstDebugViewer.GUI.app import App
|
||||
|
||||
|
|
|
@ -21,8 +21,8 @@
|
|||
|
||||
import os.path
|
||||
|
||||
import gobject
|
||||
import gtk
|
||||
from gi.repository import GObject
|
||||
from gi.repository import Gtk
|
||||
|
||||
from GstDebugViewer import Common
|
||||
from GstDebugViewer.GUI.columns import ViewColumnManager
|
||||
|
@ -94,7 +94,7 @@ class App (object):
|
|||
|
||||
widget "*.log_view" style "no-expander-treeview-style"
|
||||
"""
|
||||
gtk.rc_parse_string (rcstring)
|
||||
Gtk.rc_parse_string (rcstring)
|
||||
|
||||
self.open_window ()
|
||||
|
||||
|
@ -107,7 +107,7 @@ class App (object):
|
|||
def run (self):
|
||||
|
||||
try:
|
||||
Common.Main.MainLoopWrapper (gtk.main, gtk.main_quit).run ()
|
||||
Common.Main.MainLoopWrapper (Gtk.main, Gtk.main_quit).run ()
|
||||
except:
|
||||
raise
|
||||
else:
|
||||
|
@ -123,7 +123,7 @@ class App (object):
|
|||
if not self.windows:
|
||||
# GtkTreeView takes some time to go down for large files. Let's block
|
||||
# until the window is hidden:
|
||||
gobject.idle_add (gtk.main_quit)
|
||||
gtk.main ()
|
||||
GObject.idle_add (Gtk.main_quit)
|
||||
Gtk.main ()
|
||||
|
||||
gtk.main_quit ()
|
||||
Gtk.main_quit ()
|
||||
|
|
|
@ -19,7 +19,8 @@
|
|||
|
||||
"""GStreamer Debug Viewer GUI module."""
|
||||
|
||||
import gtk
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import Gdk
|
||||
|
||||
from GstDebugViewer import Data
|
||||
|
||||
|
@ -36,7 +37,7 @@ class Color (object):
|
|||
|
||||
def gdk_color (self):
|
||||
|
||||
return gtk.gdk.color_parse (self.hex_string ())
|
||||
return Gdk.color_parse (self.hex_string ())
|
||||
|
||||
def hex_string (self):
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ def _ (s):
|
|||
import logging
|
||||
|
||||
import glib
|
||||
import gtk
|
||||
from gi.repository import Gtk
|
||||
|
||||
from GstDebugViewer import Common, Data
|
||||
from GstDebugViewer.GUI.colors import LevelColorThemeTango
|
||||
|
@ -45,7 +45,7 @@ class Column (object):
|
|||
|
||||
def __init__ (self):
|
||||
|
||||
view_column = gtk.TreeViewColumn (self.label_header)
|
||||
view_column = Gtk.TreeViewColumn (self.label_header)
|
||||
view_column.props.reorderable = True
|
||||
|
||||
self.view_column = view_column
|
||||
|
@ -68,8 +68,8 @@ class TextColumn (SizedColumn):
|
|||
Column.__init__ (self)
|
||||
|
||||
column = self.view_column
|
||||
cell = gtk.CellRendererText ()
|
||||
column.pack_start (cell)
|
||||
cell = Gtk.CellRendererText ()
|
||||
column.pack_start (cell, True)
|
||||
|
||||
cell.props.yalign = 0.
|
||||
cell.props.ypad = 0
|
||||
|
@ -83,7 +83,7 @@ class TextColumn (SizedColumn):
|
|||
assert data_func
|
||||
id_ = self.id
|
||||
if id_ is not None:
|
||||
def cell_data_func (column, cell, model, tree_iter):
|
||||
def cell_data_func (column, cell, model, tree_iter, user_data):
|
||||
data_func (cell.props, model.get_value (tree_iter, id_))
|
||||
else:
|
||||
cell_data_func = data_func
|
||||
|
@ -99,7 +99,7 @@ class TextColumn (SizedColumn):
|
|||
|
||||
modify_func = self.get_modify_func ()
|
||||
id_ = self.id
|
||||
def cell_data_func (column, cell, model, tree_iter):
|
||||
def cell_data_func (column, cell, model, tree_iter, user_data):
|
||||
cell.props.text = modify_func (model.get_value (tree_iter, id_))
|
||||
column.set_cell_data_func (cell, cell_data_func)
|
||||
|
||||
|
@ -109,7 +109,7 @@ class TextColumn (SizedColumn):
|
|||
if not values:
|
||||
return SizedColumn.compute_default_size (self)
|
||||
|
||||
cell = self.view_column.get_cell_renderers ()[0]
|
||||
cell = self.view_column.get_cells ()[0]
|
||||
|
||||
if self.get_modify_func is not None:
|
||||
format = self.get_modify_func ()
|
||||
|
@ -120,7 +120,7 @@ class TextColumn (SizedColumn):
|
|||
max_width = 0
|
||||
for value in values:
|
||||
cell.props.text = format (value)
|
||||
rect, x, y, w, h = self.view_column.cell_get_size ()
|
||||
x, y, w, h = self.view_column.cell_get_size ()
|
||||
max_width = max (max_width, w)
|
||||
|
||||
return max_width
|
||||
|
@ -171,7 +171,7 @@ class TimeColumn (TextColumn):
|
|||
self.base_time = base_time
|
||||
|
||||
column = self.view_column
|
||||
cell = column.get_cell_renderers ()[0]
|
||||
cell = column.get_cells ()[0]
|
||||
self.update_modify_func (column, cell)
|
||||
|
||||
class LevelColumn (TextColumn):
|
||||
|
@ -184,7 +184,7 @@ class LevelColumn (TextColumn):
|
|||
|
||||
TextColumn.__init__ (self)
|
||||
|
||||
cell = self.view_column.get_cell_renderers ()[0]
|
||||
cell = self.view_column.get_cells ()[0]
|
||||
cell.props.xalign = .5
|
||||
|
||||
@staticmethod
|
||||
|
@ -278,7 +278,7 @@ class CodeColumn (TextColumn):
|
|||
|
||||
filename_id = LogModelBase.COL_FILENAME
|
||||
line_number_id = LogModelBase.COL_LINE_NUMBER
|
||||
def filename_data_func (column, cell, model, tree_iter):
|
||||
def filename_data_func (column, cell, model, tree_iter, user_data):
|
||||
args = model.get (tree_iter, filename_id, line_number_id)
|
||||
cell.props.text = "%s:%i" % args
|
||||
|
||||
|
@ -325,7 +325,7 @@ class MessageColumn (TextColumn):
|
|||
highlighters = self.highlighters
|
||||
id_ = LazyLogModel.COL_MESSAGE
|
||||
|
||||
def message_data_func (column, cell, model, tree_iter):
|
||||
def message_data_func (column, cell, model, tree_iter, user_data):
|
||||
|
||||
msg = model.get_value (tree_iter, id_)
|
||||
|
||||
|
@ -382,7 +382,7 @@ class ColumnManager (Common.GUI.Manager):
|
|||
self.columns = []
|
||||
self.column_order = list (self.column_classes)
|
||||
|
||||
self.action_group = gtk.ActionGroup ("ColumnActions")
|
||||
self.action_group = Gtk.ActionGroup ("ColumnActions")
|
||||
|
||||
def make_entry (col_class):
|
||||
return ("show-%s-column" % (col_class.name,),
|
||||
|
@ -449,12 +449,12 @@ class ColumnManager (Common.GUI.Manager):
|
|||
self.default_sort = tree_sortable_get_sort_column_id (sort_model)
|
||||
|
||||
sort_model.set_sort_column_id (TREE_SORTABLE_UNSORTED_COLUMN_ID,
|
||||
gtk.SORT_ASCENDING)
|
||||
Gtk.SortType.ASCENDING)
|
||||
|
||||
def set_zoom (self, scale):
|
||||
|
||||
for column in self.columns:
|
||||
cell = column.view_column.get_cell_renderers ()[0]
|
||||
cell = column.view_column.get_cells ()[0]
|
||||
cell.props.scale = scale
|
||||
column.view_column.queue_resize ()
|
||||
|
||||
|
@ -485,9 +485,9 @@ class ColumnManager (Common.GUI.Manager):
|
|||
pos = self.__get_column_insert_position (column)
|
||||
|
||||
if self.view.props.fixed_height_mode:
|
||||
column.view_column.props.sizing = gtk.TREE_VIEW_COLUMN_FIXED
|
||||
column.view_column.props.sizing = Gtk.TreeViewColumnSizing.FIXED
|
||||
|
||||
cell = column.view_column.get_cell_renderers ()[0]
|
||||
cell = column.view_column.get_cells ()[0]
|
||||
cell.props.scale = self.zoom
|
||||
|
||||
self.columns.insert (pos, column)
|
||||
|
@ -672,7 +672,7 @@ class WrappingMessageColumn (MessageColumn):
|
|||
|
||||
col = self.view_column
|
||||
col.props.max_width = width
|
||||
col.get_cell_renderers ()[0].props.wrap_width = width
|
||||
col.get_cells ()[0].props.wrap_width = width
|
||||
col.queue_resize ()
|
||||
|
||||
class LineViewColumnManager (ColumnManager):
|
||||
|
|
|
@ -23,18 +23,19 @@ from array import array
|
|||
from bisect import bisect_left
|
||||
import logging
|
||||
|
||||
import gobject
|
||||
import gtk
|
||||
from gi.repository import GObject
|
||||
from gi.repository import Gtk
|
||||
|
||||
from GstDebugViewer import Common, Data
|
||||
|
||||
class LogModelBase (gtk.GenericTreeModel):
|
||||
|
||||
class LogModelBase (Common.GUI.GenericTreeModel):
|
||||
|
||||
__metaclass__ = Common.GUI.MetaModel
|
||||
|
||||
columns = ("COL_TIME", gobject.TYPE_UINT64,
|
||||
columns = ("COL_TIME", GObject.TYPE_UINT64,
|
||||
"COL_PID", int,
|
||||
"COL_THREAD", gobject.TYPE_UINT64,
|
||||
"COL_THREAD", GObject.TYPE_UINT64,
|
||||
"COL_LEVEL", object,
|
||||
"COL_CATEGORY", str,
|
||||
"COL_FILENAME", str,
|
||||
|
@ -45,7 +46,7 @@ class LogModelBase (gtk.GenericTreeModel):
|
|||
|
||||
def __init__ (self):
|
||||
|
||||
gtk.GenericTreeModel.__init__ (self)
|
||||
Common.GUI.GenericTreeModel.__init__ (self)
|
||||
|
||||
##self.props.leak_references = False
|
||||
|
||||
|
@ -76,7 +77,7 @@ class LogModelBase (gtk.GenericTreeModel):
|
|||
|
||||
def on_get_flags (self):
|
||||
|
||||
flags = gtk.TREE_MODEL_LIST_ONLY | gtk.TREE_MODEL_ITERS_PERSIST
|
||||
flags = Gtk.TreeModelFlags.LIST_ONLY | Gtk.TreeModelFlags.ITERS_PERSIST
|
||||
|
||||
return flags
|
||||
|
||||
|
|
|
@ -29,8 +29,9 @@ from bisect import bisect_right, bisect_left
|
|||
import logging
|
||||
|
||||
import glib
|
||||
import gobject
|
||||
import gtk
|
||||
from gi.repository import GObject
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import Gdk
|
||||
|
||||
from GstDebugViewer import Common, Data, Main
|
||||
from GstDebugViewer.GUI.columns import LineViewColumnManager, ViewColumnManager
|
||||
|
@ -180,16 +181,16 @@ class ProgressDialog (object):
|
|||
|
||||
def __init__ (self, window, title = ""):
|
||||
|
||||
bar = gtk.InfoBar ()
|
||||
bar.props.message_type = gtk.MESSAGE_INFO
|
||||
bar = Gtk.InfoBar ()
|
||||
bar.props.message_type = Gtk.MessageType.INFO
|
||||
bar.connect ("response", self.__handle_info_bar_response)
|
||||
bar.add_button (gtk.STOCK_CANCEL, 1)
|
||||
bar.add_button (Gtk.STOCK_CANCEL, 1)
|
||||
area_box = bar.get_content_area ()
|
||||
box = gtk.HBox (spacing = 8)
|
||||
box = Gtk.HBox (spacing = 8)
|
||||
|
||||
box.pack_start (gtk.Label (title), False, False, 0)
|
||||
box.pack_start (Gtk.Label(label=title), False, False, 0)
|
||||
|
||||
progress = gtk.ProgressBar ()
|
||||
progress = Gtk.ProgressBar ()
|
||||
box.pack_start (progress, False, False, 0)
|
||||
|
||||
area_box.pack_start (box, False, False, 0)
|
||||
|
@ -229,7 +230,7 @@ class Window (object):
|
|||
|
||||
self.actions = Common.GUI.Actions ()
|
||||
|
||||
group = gtk.ActionGroup ("MenuActions")
|
||||
group = Gtk.ActionGroup ("MenuActions")
|
||||
group.add_actions ([("AppMenuAction", None, _("_Application")),
|
||||
("ViewMenuAction", None, _("_View")),
|
||||
("ViewColumnsMenuAction", None, _("_Columns")),
|
||||
|
@ -237,26 +238,26 @@ class Window (object):
|
|||
("LineViewContextMenuAction", None, "")])
|
||||
self.actions.add_group (group)
|
||||
|
||||
group = gtk.ActionGroup ("WindowActions")
|
||||
group.add_actions ([("new-window", gtk.STOCK_NEW, _("_New Window"), "<Ctrl>N"),
|
||||
("open-file", gtk.STOCK_OPEN, _("_Open File"), "<Ctrl>O"),
|
||||
("reload-file", gtk.STOCK_REFRESH, _("_Reload File"), "<Ctrl>R"),
|
||||
("close-window", gtk.STOCK_CLOSE, _("Close _Window"), "<Ctrl>W"),
|
||||
("cancel-load", gtk.STOCK_CANCEL, None,),
|
||||
("clear-line-view", gtk.STOCK_CLEAR, None),
|
||||
group = Gtk.ActionGroup ("WindowActions")
|
||||
group.add_actions ([("new-window", Gtk.STOCK_NEW, _("_New Window"), "<Ctrl>N"),
|
||||
("open-file", Gtk.STOCK_OPEN, _("_Open File"), "<Ctrl>O"),
|
||||
("reload-file", Gtk.STOCK_REFRESH, _("_Reload File"), "<Ctrl>R"),
|
||||
("close-window", Gtk.STOCK_CLOSE, _("Close _Window"), "<Ctrl>W"),
|
||||
("cancel-load", Gtk.STOCK_CANCEL, None,),
|
||||
("clear-line-view", Gtk.STOCK_CLEAR, None),
|
||||
("show-about", None, _("About GStreamer Debug Viewer",)),
|
||||
("enlarge-text", gtk.STOCK_ZOOM_IN, _("Enlarge Text"), "<Ctrl>plus"),
|
||||
("shrink-text", gtk.STOCK_ZOOM_OUT, _("Shrink Text"), "<Ctrl>minus"),
|
||||
("reset-text", gtk.STOCK_ZOOM_100, _("Normal Text Size"), "<Ctrl>0")])
|
||||
("enlarge-text", Gtk.STOCK_ZOOM_IN, _("Enlarge Text"), "<Ctrl>plus"),
|
||||
("shrink-text", Gtk.STOCK_ZOOM_OUT, _("Shrink Text"), "<Ctrl>minus"),
|
||||
("reset-text", Gtk.STOCK_ZOOM_100, _("Normal Text Size"), "<Ctrl>0")])
|
||||
self.actions.add_group (group)
|
||||
self.actions.reload_file.props.sensitive = False
|
||||
|
||||
group = gtk.ActionGroup ("RowActions")
|
||||
group = Gtk.ActionGroup ("RowActions")
|
||||
group.add_actions ([("hide-before-line", None, _("Hide lines before this point")),
|
||||
("hide-after-line", None, _("Hide lines after this point")),
|
||||
("show-hidden-lines", None, _("Show hidden lines")),
|
||||
("edit-copy-line", gtk.STOCK_COPY, _("Copy line"), "<Ctrl>C"),
|
||||
("edit-copy-message", gtk.STOCK_COPY, _("Copy message"), ""),
|
||||
("edit-copy-line", Gtk.STOCK_COPY, _("Copy line"), "<Ctrl>C"),
|
||||
("edit-copy-message", Gtk.STOCK_COPY, _("Copy message"), ""),
|
||||
("set-base-time", None, _("Set base time")),
|
||||
("hide-log-level", None, _("Hide log level")),
|
||||
("hide-log-category", None, _("Hide log category")),
|
||||
|
@ -327,8 +328,8 @@ class Window (object):
|
|||
self.window_state.attach (window = self.gtk_window,
|
||||
state = self.app.state_section)
|
||||
|
||||
self.clipboard = gtk.Clipboard (self.gtk_window.get_display (),
|
||||
gtk.gdk.SELECTION_CLIPBOARD)
|
||||
self.clipboard = Gtk.Clipboard.get_for_display (self.gtk_window.get_display (),
|
||||
Gdk.SELECTION_CLIPBOARD)
|
||||
|
||||
for action_name, handler in iter_actions (self):
|
||||
action = getattr (self.actions, action_name)
|
||||
|
@ -348,7 +349,7 @@ class Window (object):
|
|||
# FIXME: With multiple selection mode, browsing the list with key
|
||||
# up/down slows to a crawl! WTF is wrong with this stupid widget???
|
||||
sel = self.log_view.get_selection ()
|
||||
sel.set_mode (gtk.SELECTION_BROWSE)
|
||||
sel.set_mode (Gtk.SelectionMode.BROWSE)
|
||||
|
||||
self.line_view.attach (self)
|
||||
|
||||
|
@ -515,13 +516,13 @@ class Window (object):
|
|||
@action
|
||||
def handle_open_file_action_activate (self, action):
|
||||
|
||||
dialog = gtk.FileChooserDialog (None, self.gtk_window,
|
||||
gtk.FILE_CHOOSER_ACTION_OPEN,
|
||||
(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
|
||||
gtk.STOCK_OPEN, gtk.RESPONSE_ACCEPT,))
|
||||
dialog = Gtk.FileChooserDialog (None, self.gtk_window,
|
||||
Gtk.FileChooserAction.OPEN,
|
||||
(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
|
||||
Gtk.STOCK_OPEN, Gtk.ResponseType.ACCEPT,))
|
||||
response = dialog.run ()
|
||||
dialog.hide ()
|
||||
if response == gtk.RESPONSE_ACCEPT:
|
||||
if response == Gtk.ResponseType.ACCEPT:
|
||||
self.set_log_file (dialog.get_filename ())
|
||||
dialog.destroy ()
|
||||
|
||||
|
@ -544,7 +545,7 @@ class Window (object):
|
|||
self.hide_info ()
|
||||
self.progress_dialog = None
|
||||
if self.update_progress_id is not None:
|
||||
gobject.source_remove (self.update_progress_id)
|
||||
GObject.source_remove (self.update_progress_id)
|
||||
self.update_progress_id = None
|
||||
|
||||
self.set_sensitive (True)
|
||||
|
@ -699,7 +700,7 @@ class Window (object):
|
|||
self.log_view.set_model (None)
|
||||
self.log_filter.add_filter (filter, dispatcher = dispatcher)
|
||||
|
||||
gobject.timeout_add (250, self.update_filter_progress)
|
||||
GObject.timeout_add (250, self.update_filter_progress)
|
||||
|
||||
self.set_sensitive (False)
|
||||
|
||||
|
@ -845,13 +846,13 @@ class Window (object):
|
|||
|
||||
def show_error (self, message1, message2):
|
||||
|
||||
bar = gtk.InfoBar ()
|
||||
bar.props.message_type = gtk.MESSAGE_ERROR
|
||||
bar = Gtk.InfoBar ()
|
||||
bar.props.message_type = Gtk.MessageType.ERROR
|
||||
box = bar.get_content_area ()
|
||||
|
||||
markup = "<b>%s</b> %s" % (glib.markup_escape_text (message1),
|
||||
glib.markup_escape_text (message2),)
|
||||
label = gtk.Label ()
|
||||
label = Gtk.Label ()
|
||||
label.props.use_markup = True
|
||||
label.props.label = markup
|
||||
label.props.selectable = True
|
||||
|
@ -866,7 +867,7 @@ class Window (object):
|
|||
self.progress_dialog = ProgressDialog (self, _("Loading log file"))
|
||||
self.show_info (self.progress_dialog.widget)
|
||||
self.progress_dialog.handle_cancel = self.handle_load_progress_dialog_cancel
|
||||
self.update_progress_id = gobject.timeout_add (250, self.update_load_progress)
|
||||
self.update_progress_id = GObject.timeout_add (250, self.update_load_progress)
|
||||
|
||||
self.set_sensitive (False)
|
||||
|
||||
|
@ -917,4 +918,4 @@ class Window (object):
|
|||
sel.select_path ((0,))
|
||||
return False
|
||||
|
||||
gobject.idle_add (idle_set)
|
||||
GObject.idle_add (idle_set)
|
||||
|
|
|
@ -21,13 +21,13 @@
|
|||
|
||||
from GstDebugViewer.Plugins import *
|
||||
import logging
|
||||
import gtk
|
||||
from gi.repository import Gtk
|
||||
|
||||
class FilePropertiesSentinel (object):
|
||||
|
||||
pass
|
||||
|
||||
class FilePropertiesDialog (gtk.Dialog):
|
||||
class FilePropertiesDialog (Gtk.Dialog):
|
||||
|
||||
pass
|
||||
|
||||
|
@ -35,8 +35,8 @@ class FilePropertiesFeature (FeatureBase):
|
|||
|
||||
def __init__ (self, *a, **kw):
|
||||
|
||||
self.action_group = gtk.ActionGroup ("FilePropertiesActions")
|
||||
self.action_group.add_actions ([("show-file-properties", gtk.STOCK_PROPERTIES,
|
||||
self.action_group = Gtk.ActionGroup ("FilePropertiesActions")
|
||||
self.action_group.add_actions ([("show-file-properties", Gtk.STOCK_PROPERTIES,
|
||||
_("_Properties"), "<Ctrl>P")])
|
||||
|
||||
def attach (self, window):
|
||||
|
@ -47,7 +47,7 @@ class FilePropertiesFeature (FeatureBase):
|
|||
self.merge_id = ui.new_merge_id ()
|
||||
ui.add_ui (self.merge_id, "/menubar/FileMenu/FileMenuAdditions",
|
||||
"FileProperties", "show-file-properties",
|
||||
gtk.UI_MANAGER_MENUITEM, False)
|
||||
Gtk.UIManagerItemType.MENUITEM, False)
|
||||
|
||||
handler = self.handle_action_activate
|
||||
self.action_group.get_action ("show-file-properties").connect ("activate", handler)
|
||||
|
|
|
@ -25,7 +25,8 @@ from GstDebugViewer import Common, Data, GUI
|
|||
from GstDebugViewer.Plugins import *
|
||||
|
||||
import glib
|
||||
import gtk
|
||||
from gi.repository import GObject
|
||||
from gi.repository import Gtk
|
||||
|
||||
class SearchOperation (object):
|
||||
|
||||
|
@ -127,32 +128,32 @@ class SearchSentinel (object):
|
|||
|
||||
pass
|
||||
|
||||
class FindBarWidget (gtk.HBox):
|
||||
class FindBarWidget (Gtk.HBox):
|
||||
|
||||
__status = {"no-match-found" : _N("No match found"),
|
||||
"searching" : _N("Searching...")}
|
||||
|
||||
def __init__ (self, action_group):
|
||||
|
||||
gtk.HBox.__init__ (self)
|
||||
GObject.GObject.__init__ (self)
|
||||
|
||||
label = gtk.Label (_("Find:"))
|
||||
label = Gtk.Label(label=_("Find:"))
|
||||
self.pack_start (label, False, False, 2)
|
||||
|
||||
self.entry = gtk.Entry ()
|
||||
self.pack_start (self.entry)
|
||||
self.entry = Gtk.Entry ()
|
||||
self.pack_start (self.entry, True, True, 0)
|
||||
|
||||
prev_action = action_group.get_action ("goto-previous-search-result")
|
||||
prev_button = gtk.Button ()
|
||||
prev_action.connect_proxy (prev_button)
|
||||
prev_button = Gtk.Button ()
|
||||
prev_button.set_related_action (prev_action)
|
||||
self.pack_start (prev_button, False, False, 0)
|
||||
|
||||
next_action = action_group.get_action ("goto-next-search-result")
|
||||
next_button = gtk.Button ()
|
||||
next_action.connect_proxy (next_button)
|
||||
next_button = Gtk.Button ()
|
||||
next_button.set_related_action (next_action)
|
||||
self.pack_start (next_button, False, False, 0)
|
||||
|
||||
self.status_label = gtk.Label ()
|
||||
self.status_label = Gtk.Label ()
|
||||
self.status_label.props.xalign = 0.
|
||||
self.status_label.props.use_markup = True
|
||||
self.pack_start (self.status_label, False, False, 6)
|
||||
|
@ -170,8 +171,8 @@ class FindBarWidget (gtk.HBox):
|
|||
try:
|
||||
for status in self.__status.values ():
|
||||
self.__set_status (_(status))
|
||||
width, height = label.size_request ()
|
||||
max_width = max (max_width, width)
|
||||
req = label.size_request ()
|
||||
max_width = max (max_width, req.width)
|
||||
label.set_size_request (max_width, -1)
|
||||
finally:
|
||||
label.props.label = old_markup
|
||||
|
@ -206,7 +207,7 @@ class FindBarFeature (FeatureBase):
|
|||
|
||||
self.logger = logging.getLogger ("ui.findbar")
|
||||
|
||||
self.action_group = gtk.ActionGroup ("FindBarActions")
|
||||
self.action_group = Gtk.ActionGroup ("FindBarActions")
|
||||
self.action_group.add_toggle_actions ([("show-find-bar",
|
||||
None,
|
||||
_("Find Bar"),
|
||||
|
@ -233,7 +234,7 @@ class FindBarFeature (FeatureBase):
|
|||
|
||||
view = self.log_view
|
||||
|
||||
path = (line_index,)
|
||||
path = Gtk.TreePath((line_index,))
|
||||
|
||||
start_path, end_path = view.get_visible_range ()
|
||||
|
||||
|
@ -259,7 +260,7 @@ class FindBarFeature (FeatureBase):
|
|||
("ViewNextResult", "goto-next-search-result",),
|
||||
("ViewPrevResult", "goto-previous-search-result",)]:
|
||||
ui.add_ui (self.merge_id, "/menubar/ViewMenu/ViewMenuAdditions",
|
||||
name, action_name, gtk.UI_MANAGER_MENUITEM, False)
|
||||
name, action_name, Gtk.UIManagerItemType.MENUITEM, False)
|
||||
|
||||
box = window.widgets.vbox_view
|
||||
self.bar = FindBarWidget (self.action_group)
|
||||
|
|
|
@ -25,8 +25,9 @@ from GstDebugViewer import Common, Data
|
|||
from GstDebugViewer.GUI.colors import LevelColorThemeTango, ThreadColorThemeTango
|
||||
from GstDebugViewer.Plugins import *
|
||||
|
||||
import gobject
|
||||
import gtk
|
||||
from gi.repository import GObject
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import Gdk
|
||||
import cairo
|
||||
|
||||
def iter_model_reversed (model):
|
||||
|
@ -267,13 +268,13 @@ class UpdateProcess (object):
|
|||
|
||||
pass
|
||||
|
||||
class VerticalTimelineWidget (gtk.DrawingArea):
|
||||
class VerticalTimelineWidget (Gtk.DrawingArea):
|
||||
|
||||
__gtype_name__ = "GstDebugViewerVerticalTimelineWidget"
|
||||
|
||||
def __init__ (self, log_view):
|
||||
|
||||
gtk.DrawingArea.__init__ (self)
|
||||
GObject.GObject.__init__ (self)
|
||||
|
||||
self.logger = logging.getLogger ("ui.vtimeline")
|
||||
|
||||
|
@ -306,7 +307,11 @@ class VerticalTimelineWidget (gtk.DrawingArea):
|
|||
def __draw (self, drawable):
|
||||
|
||||
ctx = drawable.cairo_create ()
|
||||
x, y, w, h = self.get_allocation ()
|
||||
alloc = self.get_allocation ()
|
||||
x = alloc.x
|
||||
y = alloc.y
|
||||
w = alloc.width
|
||||
h = alloc.height
|
||||
|
||||
# White background rectangle.
|
||||
ctx.set_line_width (0.)
|
||||
|
@ -419,23 +424,23 @@ class VerticalTimelineWidget (gtk.DrawingArea):
|
|||
self.params = None
|
||||
self.queue_draw ()
|
||||
|
||||
class TimelineWidget (gtk.DrawingArea):
|
||||
class TimelineWidget (Gtk.DrawingArea):
|
||||
|
||||
__gtype_name__ = "GstDebugViewerTimelineWidget"
|
||||
|
||||
__gsignals__ = {"change-position" : (gobject.SIGNAL_RUN_LAST,
|
||||
gobject.TYPE_NONE,
|
||||
(gobject.TYPE_INT,),)}
|
||||
__gsignals__ = {"change-position" : (GObject.SignalFlags.RUN_LAST,
|
||||
None,
|
||||
(GObject.TYPE_INT,),)}
|
||||
|
||||
def __init__ (self):
|
||||
|
||||
gtk.DrawingArea.__init__ (self)
|
||||
GObject.GObject.__init__ (self)
|
||||
|
||||
self.logger = logging.getLogger ("ui.timeline")
|
||||
|
||||
self.add_events (gtk.gdk.BUTTON1_MOTION_MASK |
|
||||
gtk.gdk.BUTTON_PRESS_MASK |
|
||||
gtk.gdk.BUTTON_RELEASE_MASK)
|
||||
self.add_events (Gdk.EventMask.BUTTON1_MOTION_MASK |
|
||||
Gdk.EventMask.BUTTON_PRESS_MASK |
|
||||
Gdk.EventMask.BUTTON_RELEASE_MASK)
|
||||
|
||||
self.process = UpdateProcess (None, None)
|
||||
self.process.handle_sentinel_progress = self.__handle_sentinel_progress
|
||||
|
@ -473,22 +478,22 @@ class TimelineWidget (gtk.DrawingArea):
|
|||
|
||||
def __ensure_offscreen (self):
|
||||
|
||||
x, y, width, height = self.get_allocation ()
|
||||
if self.__offscreen_size == (width, height):
|
||||
alloc = self.get_allocation ()
|
||||
if self.__offscreen_size == (alloc.width, alloc.height):
|
||||
return
|
||||
|
||||
self.__offscreen = gtk.gdk.Pixmap (self.window, width, height, -1)
|
||||
self.__offscreen_size = (width, height)
|
||||
self.__offscreen_dirty = (0, width)
|
||||
self.__offscreen = Gdk.Pixmap (self.window, alloc.width, alloc.height, -1)
|
||||
self.__offscreen_size = (alloc.width, alloc.height)
|
||||
self.__offscreen_dirty = (0, alloc.width)
|
||||
if not self.__offscreen:
|
||||
self.__offscreen_size = (0, 0)
|
||||
raise ValueError ("could not obtain pixmap")
|
||||
|
||||
def __invalidate_offscreen (self, start, stop):
|
||||
|
||||
x, y, width, height = self.get_allocation ()
|
||||
alloc = self.get_allocation ()
|
||||
if stop < 0:
|
||||
stop += width
|
||||
stop += alloc.width
|
||||
|
||||
dirty_start, dirty_stop = self.__offscreen_dirty
|
||||
if dirty_start != dirty_stop:
|
||||
|
@ -502,22 +507,22 @@ class TimelineWidget (gtk.DrawingArea):
|
|||
# Just like in __draw_offscreen. FIXME: Need this in one place!
|
||||
start -= 8
|
||||
stop += 8
|
||||
self.queue_draw_area (start, 0, stop - start, height)
|
||||
self.queue_draw_area (start, 0, stop - start, alloc.height)
|
||||
|
||||
def __draw_from_offscreen (self, rect = None):
|
||||
|
||||
if not self.props.visible:
|
||||
return
|
||||
|
||||
x, y, width, height = self.get_allocation ()
|
||||
alloc = self.get_allocation ()
|
||||
offscreen_width, offscreen_height = self.__offscreen_size
|
||||
if rect is None:
|
||||
rect = (0, 0, width, height)
|
||||
rect = (0, 0, alloc.width, alloc.height)
|
||||
|
||||
# Fill the background (where the offscreen pixmap doesn't fit) with
|
||||
# white. This happens after enlarging the window, until all sentinels
|
||||
# have finished running.
|
||||
if offscreen_width < width or offscreen_height < height:
|
||||
if offscreen_width < alloc.width or offscreen_height < alloc.height:
|
||||
ctx = self.window.cairo_create ()
|
||||
|
||||
if rect:
|
||||
|
@ -526,17 +531,17 @@ class TimelineWidget (gtk.DrawingArea):
|
|||
rect.y + rect.height)
|
||||
ctx.clip ()
|
||||
|
||||
if offscreen_width < width:
|
||||
ctx.rectangle (offscreen_width, 0, width, offscreen_height)
|
||||
if offscreen_height < height:
|
||||
if offscreen_width < alloc.width:
|
||||
ctx.rectangle (offscreen_width, 0, alloc.width, offscreen_height)
|
||||
if offscreen_height < alloc.height:
|
||||
ctx.new_path ()
|
||||
ctx.rectangle (0, offscreen_height, width, height)
|
||||
ctx.rectangle (0, offscreen_height, alloc.width, alloc.height)
|
||||
|
||||
ctx.set_line_width (0.)
|
||||
ctx.set_source_rgb (1., 1., 1.)
|
||||
ctx.fill ()
|
||||
|
||||
gc = gtk.gdk.GC (self.window)
|
||||
gc = Gdk.GC (self.window)
|
||||
x, y, width, height = rect
|
||||
self.window.draw_drawable (gc, self.__offscreen, x, y, x, y, width, height)
|
||||
self.__draw_position (self.window, clip = rect)
|
||||
|
@ -550,7 +555,7 @@ class TimelineWidget (gtk.DrawingArea):
|
|||
self.__dist_sentinel_progress = 0
|
||||
self.process.freq_sentinel = LineFrequencySentinel (model)
|
||||
self.process.dist_sentinel = LevelDistributionSentinel (self.process.freq_sentinel, model)
|
||||
width = self.get_allocation ()[2]
|
||||
width = self.get_allocation ().width
|
||||
self.process.freq_sentinel.run_for (width)
|
||||
self.process.run ()
|
||||
|
||||
|
@ -570,15 +575,15 @@ class TimelineWidget (gtk.DrawingArea):
|
|||
if not self.process.freq_sentinel.data:
|
||||
return
|
||||
|
||||
x, y, width, height = self.get_allocation ()
|
||||
alloc = self.get_allocation ()
|
||||
|
||||
# Queue old position rectangle for redraw:
|
||||
if self.__position_ts_range is not None:
|
||||
start, stop = self.ts_range_to_position (*self.__position_ts_range)
|
||||
self.queue_draw_area (start - 1, 0, stop - start + 2, height)
|
||||
self.queue_draw_area (start - 1, 0, stop - start + 2, alloc.height)
|
||||
# And the new one:
|
||||
start, stop = self.ts_range_to_position (start_ts, end_ts)
|
||||
self.queue_draw_area (start - 1, 0, stop - start + 2, height)
|
||||
self.queue_draw_area (start - 1, 0, stop - start + 2, alloc.height)
|
||||
|
||||
self.__position_ts_range = (start_ts, end_ts,)
|
||||
|
||||
|
@ -766,7 +771,7 @@ class TimelineWidget (gtk.DrawingArea):
|
|||
return
|
||||
|
||||
ctx = drawable.cairo_create ()
|
||||
x, y, width, height = self.get_allocation ()
|
||||
height = self.get_allocation ().height
|
||||
|
||||
if clip:
|
||||
ctx.rectangle (*clip)
|
||||
|
@ -840,13 +845,13 @@ class TimelineWidget (gtk.DrawingArea):
|
|||
|
||||
x, y, mod = self.window.get_pointer ()
|
||||
|
||||
if event.state & gtk.gdk.BUTTON1_MASK:
|
||||
if event.get_state() & Gdk.ModifierType.BUTTON1_MASK:
|
||||
self.emit ("change-position", int (x))
|
||||
gtk.gdk.event_request_motions (event)
|
||||
Gdk.event_request_motions (event)
|
||||
return True
|
||||
else:
|
||||
self._handle_motion (x, y)
|
||||
gtk.gdk.event_request_motions (event)
|
||||
Gdk.event_request_motions (event)
|
||||
return False
|
||||
|
||||
def _handle_motion (self, x, y):
|
||||
|
@ -868,18 +873,18 @@ class AttachedWindow (object):
|
|||
self.merge_id = ui.new_merge_id ()
|
||||
ui.add_ui (self.merge_id, "/menubar/ViewMenu/ViewMenuAdditions",
|
||||
"ViewTimeline", "show-timeline",
|
||||
gtk.UI_MANAGER_MENUITEM, False)
|
||||
Gtk.UIManagerItemType.MENUITEM, False)
|
||||
|
||||
ui.add_ui (self.merge_id, "/", "TimelineContextMenu", None,
|
||||
gtk.UI_MANAGER_POPUP, False)
|
||||
Gtk.UIManagerItemType.POPUP, False)
|
||||
# TODO: Make hide before/after operate on the partition that the mouse
|
||||
# is pointed at instead of the currently selected line.
|
||||
# ui.add_ui (self.merge_id, "/TimelineContextMenu", "TimelineHideLinesBefore",
|
||||
# "hide-before-line", gtk.UI_MANAGER_MENUITEM, False)
|
||||
# "hide-before-line", Gtk.UIManagerItemType.MENUITEM, False)
|
||||
# ui.add_ui (self.merge_id, "/TimelineContextMenu", "TimelineHideLinesAfter",
|
||||
# "hide-after-line", gtk.UI_MANAGER_MENUITEM, False)
|
||||
# "hide-after-line", Gtk.UIManagerItemType.MENUITEM, False)
|
||||
ui.add_ui (self.merge_id, "/TimelineContextMenu", "TimelineShowHiddenLines",
|
||||
"show-hidden-lines", gtk.UI_MANAGER_MENUITEM, False)
|
||||
"show-hidden-lines", Gtk.UIManagerItemType.MENUITEM, False)
|
||||
|
||||
box = window.get_top_attach_point ()
|
||||
|
||||
|
@ -928,7 +933,7 @@ class AttachedWindow (object):
|
|||
|
||||
self.idle_scroll_path = None
|
||||
if self.idle_scroll_id is not None:
|
||||
gobject.source_remove (self.idle_scroll_id)
|
||||
GObject.source_remove (self.idle_scroll_id)
|
||||
self.idle_scroll_id = None
|
||||
|
||||
def handle_detach_log_file (self, log_file):
|
||||
|
@ -953,7 +958,7 @@ class AttachedWindow (object):
|
|||
self.update_timeline_position ()
|
||||
self.vtimeline.update ()
|
||||
return False
|
||||
gobject.idle_add (idle_update, priority = gobject.PRIORITY_LOW)
|
||||
GObject.idle_add (idle_update, priority = GObject.PRIORITY_LOW)
|
||||
|
||||
def handle_log_view_adjustment_value_changed (self, adj):
|
||||
|
||||
|
@ -1016,7 +1021,7 @@ class AttachedWindow (object):
|
|||
self.idle_scroll_path = path
|
||||
|
||||
if self.idle_scroll_id is None:
|
||||
self.idle_scroll_id = gobject.idle_add (self.idle_scroll)
|
||||
self.idle_scroll_id = GObject.idle_add (self.idle_scroll)
|
||||
|
||||
return False
|
||||
|
||||
|
@ -1041,7 +1046,7 @@ class TimelineFeature (FeatureBase):
|
|||
|
||||
self.logger = logging.getLogger ("ui.timeline")
|
||||
|
||||
self.action_group = gtk.ActionGroup ("TimelineActions")
|
||||
self.action_group = Gtk.ActionGroup ("TimelineActions")
|
||||
self.action_group.add_toggle_actions ([("show-timeline",
|
||||
None, _("_Timeline"),)])
|
||||
|
||||
|
|
28
debug-viewer/README
Normal file
28
debug-viewer/README
Normal file
|
@ -0,0 +1,28 @@
|
|||
# how to build #
|
||||
|
||||
./setup.py build; sudo ./setup.py install --prefix=/usr
|
||||
sudo chmod a+r /usr/share/gst-debug-viewer/*.ui
|
||||
|
||||
# porting issues #
|
||||
|
||||
http://stackoverflow.com/questions/11025700/generictreemodel-with-pygobject-introspection-gtk-3
|
||||
|
||||
# tips #
|
||||
|
||||
OLD: prev_action.connect_proxy(prev_button)
|
||||
NEW: prev_button.set_related_action (prev_action)
|
||||
|
||||
OLD: box.pack_start (widget)
|
||||
NEW: box.pack_start (widget, True, True, 0)
|
||||
|
||||
OLD: column.pack_start (cell)
|
||||
NEW: column.pack_start (cell, True)
|
||||
|
||||
OLD: view_column.get_cell_renderers ()
|
||||
NEW: column.get_cells ()
|
||||
|
||||
GenericTreeModel
|
||||
http://cgit.freedesktop.org/gstreamer/gst-devtools/tree/debug-viewer/GstDebugViewer/GUI/models.py
|
||||
https://gist.github.com/andialbrecht/4463278
|
||||
http://mailman.daa.com.au/cgi-bin/pipermail/pygtk/2012-December/020510.html
|
||||
https://github.com/GNOME/pygobject/blob/master/pygtkcompat/generictreemodel.py
|
|
@ -26,11 +26,9 @@ import os.path
|
|||
from glob import glob
|
||||
import time
|
||||
|
||||
import pygtk
|
||||
pygtk.require ("2.0")
|
||||
del pygtk
|
||||
import gi
|
||||
|
||||
import gobject
|
||||
from gi.repository import GObject
|
||||
|
||||
sys.path.insert (0, os.path.join (sys.path[0], os.pardir))
|
||||
|
||||
|
@ -40,7 +38,7 @@ class TestParsingPerformance (object):
|
|||
|
||||
def __init__ (self, filename):
|
||||
|
||||
self.main_loop = gobject.MainLoop ()
|
||||
self.main_loop = GObject.MainLoop ()
|
||||
self.log_file = Data.LogFile (filename, Common.Data.DefaultDispatcher ())
|
||||
self.log_file.consumers.append (self)
|
||||
|
||||
|
|
Loading…
Reference in a new issue