示例#1
0
 def __init__(self, selection, _log):
     self.clipboard = gtk.Clipboard(selection=selection)
     self.selection = selection
     self._log = _log
     self.owned_label = label()
     self.get_targets = gtk.combo_box_new_text()
     self.get_targets.set_sensitive(False)
     self.get_targets.connect("changed", self.get_target_changed)
     self.set_targets = gtk.combo_box_new_text()
     self.set_targets.append_text("STRING")
     self.set_targets.append_text("UTF8_STRING")
     self.set_targets.set_active(0)
     self.set_targets.connect("changed", self.set_target_changed)
     self.value_label = label()
     self.value_entry = gtk.Entry(max=100)
     self.value_entry.set_width_chars(32)
     self.clear_label_btn = gtk.Button("X")
     self.clear_label_btn.connect("clicked", self.clear_label)
     self.clear_entry_btn = gtk.Button("X")
     self.clear_entry_btn.connect("clicked", self.clear_entry)
     self.get_get_targets_btn = gtk.Button("Get Targets")
     self.get_get_targets_btn.connect("clicked", self.do_get_targets)
     self.get_target_btn = gtk.Button("Get Target")
     self.get_target_btn.connect("clicked", self.do_get_target)
     self.get_target_btn.set_sensitive(False)
     self.set_target_btn = gtk.Button("Set Target")
     self.set_target_btn.connect("clicked", self.do_set_target)
     self.get_string_btn = gtk.Button("Get String")
     self.get_string_btn.connect("clicked", self.do_get_string)
     self.set_string_btn = gtk.Button("Set String")
     self.set_string_btn.connect("clicked", self.do_set_string)
     self.clipboard.connect("owner-change", self.owner_changed)
     self.log("ready")
示例#2
0
 def __init__(self, selection, _log):
     atom = Gdk.Atom.intern(selection, False)
     self.clipboard = Gtk.Clipboard.get(atom)
     self.selection = selection
     self._log = _log
     self.owned_label = label()
     self.get_targets = Gtk.ComboBoxText()
     self.get_targets.set_sensitive(False)
     self.get_targets.connect("changed", self.get_target_changed)
     self.set_targets = Gtk.ComboBoxText()
     self.set_targets.append_text("STRING")
     self.set_targets.append_text("UTF8_STRING")
     self.set_targets.set_active(0)
     self.set_targets.connect("changed", self.set_target_changed)
     self.value_label = label()
     self.value_entry = Gtk.Entry()
     self.value_entry.set_max_length(100)
     self.value_entry.set_width_chars(32)
     self.clear_label_btn = Gtk.Button("X")
     self.clear_label_btn.connect("clicked", self.clear_label)
     self.clear_entry_btn = Gtk.Button("X")
     self.clear_entry_btn.connect("clicked", self.clear_entry)
     self.get_get_targets_btn = Gtk.Button("Get Targets")
     self.get_get_targets_btn.connect("clicked", self.do_get_targets)
     self.get_target_btn = Gtk.Button("Get Target")
     self.get_target_btn.connect("clicked", self.do_get_target)
     self.get_target_btn.set_sensitive(False)
     self.set_target_btn = Gtk.Button("Set Target")
     self.set_target_btn.connect("clicked", self.do_set_target)
     self.get_string_btn = Gtk.Button("Get String")
     self.get_string_btn.connect("clicked", self.do_get_string)
     self.set_string_btn = Gtk.Button("Set String")
     self.set_string_btn.connect("clicked", self.do_set_string)
     self.clipboard.connect("owner-change", self.owner_changed)
     self.log("ready")
示例#3
0
	def __init__(self, selection, _log):
		self.clipboard = gtk.Clipboard(selection=selection)
		self.selection = selection
		self._log = _log
		self.owned_label = label()
		self.get_targets = gtk.combo_box_new_text()
		self.get_targets.set_sensitive(False)
		self.get_targets.connect("changed", self.get_target_changed)
		self.set_targets = gtk.combo_box_new_text()
		self.set_targets.append_text("STRING")
		self.set_targets.append_text("UTF8_STRING")
		self.set_targets.set_active(0)
		self.set_targets.connect("changed", self.set_target_changed)
		self.value_label = label()
		self.value_entry = gtk.Entry(max=100)
		self.value_entry.set_width_chars(32)
		self.clear_label_btn = gtk.Button("X")
		self.clear_label_btn.connect("clicked", self.clear_label)
		self.clear_entry_btn = gtk.Button("X")
		self.clear_entry_btn.connect("clicked", self.clear_entry)
		self.get_get_targets_btn = gtk.Button("Get Targets")
		self.get_get_targets_btn.connect("clicked", self.do_get_targets)
		self.get_target_btn = gtk.Button("Get Target")
		self.get_target_btn.connect("clicked", self.do_get_target)
		self.get_target_btn.set_sensitive(False)
		self.set_target_btn = gtk.Button("Set Target")
		self.set_target_btn.connect("clicked", self.do_set_target)
		self.get_string_btn = gtk.Button("Get String")
		self.get_string_btn.connect("clicked", self.do_get_string)
		self.set_string_btn = gtk.Button("Set String")
		self.set_string_btn.connect("clicked", self.do_set_string)
		self.clipboard.connect("owner-change", self.owner_changed)
		self.log("ready")
示例#4
0
    def __init__(self):
        self.window = Gtk.Window()
        self.window.connect("destroy", self.destroy)
        self.window.set_default_size(640, 300)
        self.window.set_border_width(20)
        self.window.set_position(Gtk.WindowPosition.CENTER)
        self.window.set_title("Clipboard Test Tool")

        vbox = Gtk.VBox(False, 0)
        vbox.set_spacing(15)

        self.log = deque(maxlen=25)
        for x in range(25):
            self.log.append("")
        self.events = Gtk.Label()
        fixed = Pango.FontDescription('monospace 9')
        self.events.modify_font(fixed)

        #how many clipboards to show:
        self.clipboards = CLIPBOARDS

        tb = TableBuilder()
        table = tb.get_table()
        labels = [label("Selection")]
        labels += [
            label("Value"),
            label("Clear"),
            label("Targets"),
            label("Actions")
        ]
        tb.add_row(*labels)
        for selection in self.clipboards:
            cs = ClipboardInstance(selection, self.add_event)
            get_actions = Gtk.HBox()
            for x in (cs.get_get_targets_btn, cs.get_target_btn,
                      cs.get_string_btn):
                get_actions.pack_start(x)
            tb.add_row(label(selection), cs.value_label, cs.clear_label_btn,
                       cs.get_targets, get_actions)
            set_actions = Gtk.HBox()
            for x in (cs.set_target_btn, cs.set_string_btn):
                set_actions.pack_start(x)
            tb.add_row(None, cs.value_entry, cs.clear_entry_btn,
                       cs.set_targets, set_actions)
        vbox.pack_start(table)
        vbox.add(self.events)

        self.window.add(vbox)
        self.window.show_all()
        icon = get_icon_pixbuf("clipboard.png")
        if icon:
            self.window.set_icon(icon)
        try:
            self.add_event(
                "ALL", "window=%s, xid=%#x" %
                (self.window, self.window.get_window().get_xid()))
        except Exception:
            self.add_event("ALL", "window=%s" % self.window)
示例#5
0
	def	__init__(self):
		self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
		self.window.connect("destroy", self.destroy)
		self.window.set_default_size(640, 300)
		self.window.set_border_width(20)

		vbox = gtk.VBox(False, 0)
		vbox.set_spacing(15)

		self.log = maxdeque(maxlen=25)
		for x in range(25):
			self.log.append("")
		self.events = gtk.Label()
		fixed = pango.FontDescription('monospace 9')
		self.events.modify_font(fixed)

		#how many clipboards to show:
		self.clipboards = ["CLIPBOARD", "PRIMARY", "SECONDARY"]
		if sys.platform.startswith("win"):
			self.clipboards = ["CLIPBOARD"]

		tb = TableBuilder()
		table = tb.get_table()
		labels = [label("Selection")]
		labels += [label("Value"), label("Clear"), label("Targets"), label("Actions")]
		tb.add_row(*labels)
		for selection in self.clipboards:
			cs = ClipboardInstance(selection, self.add_event)
			get_actions = gtk.HBox()
			for x in (cs.get_get_targets_btn, cs.get_target_btn, cs.get_string_btn):
				get_actions.pack_start(x)
			tb.add_row(label(selection), cs.value_label, cs.clear_label_btn, cs.get_targets, get_actions)
			set_actions = gtk.HBox()
			for x in (cs.set_target_btn, cs.set_string_btn):
				set_actions.pack_start(x)
			tb.add_row(None, cs.value_entry, cs.clear_entry_btn, cs.set_targets, set_actions)
		vbox.pack_start(table)
		vbox.add(self.events)

		self.window.add(vbox)
		self.window.show_all()
		icon = get_icon("clipboard.png")
		if icon:
			self.window.set_icon(icon)
		try:
			self.add_event("ALL", "window=%s, xid=%s" % (self.window, hex(self.window.get_window().xid)))
		except:
			self.add_event("ALL", "window=%s" % self.window)
示例#6
0
 def server_vinfo(prop):
     k = "%s.version" % prop
     fk = "%s_version" % prop
     return label(server_version_info(k, fk))
示例#7
0
 def client_vinfo(prop, fallback="unknown"):
     k = "%s.version" % prop
     return label(make_version_str(gtk_version_info.get(k, fallback)))
示例#8
0
def slabel(text="", tooltip=None, font=None):
    l = label(text, tooltip, font)
    l.set_selectable(True)
    return l
示例#9
0
    def populate_statistics(self):
        log("populate_statistics()")
        if time.time()-self.last_populate_statistics<1.0:
            #don't repopulate more than every second
            return True
        self.last_populate_statistics = time.time()
        if self.client.server_info_request:
            self.client.send_info_request()
        def setall(labels, values):
            assert len(labels)==len(values), "%s labels and %s values (%s vs %s)" % (len(labels), len(values), labels, values)
            for i in range(len(labels)):
                l = labels[i]
                v = values[i]
                l.set_text(str(v))
        def setlabels(labels, values, rounding=int):
            if len(values)==0:
                return
            avg = sum(values)/len(values)
            svalues = sorted(values)
            l = len(svalues)
            assert l>0
            if l<10:
                index = l-1
            else:
                index = int(l*90/100)
            index = max(0, min(l-1, index))
            pct = svalues[index]
            disp = values[-1], min(values), avg, pct, max(values)
            rounded_values = [rounding(v) for v in disp]
            setall(labels, rounded_values)

        if len(self.client.server_ping_latency)>0:
            spl = [1000.0*x for _,x in list(self.client.server_ping_latency)]
            setlabels(self.server_latency_labels, spl)
        if len(self.client.client_ping_latency)>0:
            cpl = [1000.0*x for _,x in list(self.client.client_ping_latency)]
            setlabels(self.client_latency_labels, cpl)
        if self.client.windows_enabled:
            if self.client.server_info_request:
                setall(self.batch_labels, self.values_from_info("batch_delay", "batch.delay"))
                setall(self.damage_labels, self.values_from_info("damage_out_latency", "damage.out_latency"))
                setall(self.quality_labels, self.all_values_from_info("quality", "encoding.quality"))
                setall(self.speed_labels, self.all_values_from_info("speed", "encoding.speed"))

            region_sizes = []
            rps = []
            pps = []
            decoding_latency = []
            if len(self.client.pixel_counter)>0:
                min_time = None
                max_time = None
                regions_per_second = {}
                pixels_per_second = {}
                for start_time, end_time, size in self.client.pixel_counter:
                    decoding_latency.append(int(1000.0*(end_time-start_time)))
                    region_sizes.append(size)
                    if min_time is None or min_time>end_time:
                        min_time = end_time
                    if max_time is None or max_time<end_time:
                        max_time = end_time
                    time_in_seconds = int(end_time)
                    regions = regions_per_second.get(time_in_seconds, 0)
                    regions_per_second[time_in_seconds] = regions+1
                    pixels = pixels_per_second.get(time_in_seconds, 0)
                    pixels_per_second[time_in_seconds] = pixels + size
                if int(min_time)+1 < int(max_time):
                    for t in range(int(min_time)+1, int(max_time)):
                        rps.append(regions_per_second.get(t, 0))
                        pps.append(pixels_per_second.get(t, 0))
            setlabels(self.decoding_labels, decoding_latency)
            setlabels(self.regions_per_second_labels, rps)
            setlabels(self.regions_sizes_labels, region_sizes, rounding=std_unit_dec)
            setlabels(self.pixels_per_second_labels, pps, rounding=std_unit_dec)

            windows, gl, transient, trays = 0, 0, 0, 0
            for w in self.client._window_to_id.keys():
                if w.is_tray():
                    trays += 1
                elif w.is_OR():
                    transient +=1
                else:
                    windows += 1
                if w.is_GL():
                    gl += 1
            self.windows_managed_label.set_text(str(windows))
            self.transient_managed_label.set_text(str(transient))
            self.trays_managed_label.set_text(str(trays))
            if self.client.client_supports_opengl:
                self.opengl_label.set_text(str(gl))

            #remove all the current labels:
            for x in self.encoder_info_box.get_children():
                self.encoder_info_box.remove(x)
            window_encoder_stats = {}
            if self.client.server_last_info:
                #We are interested in data like:
                #window[1].encoder=x264
                #window[1].encoder.frames=1
                for k,v in self.client.server_last_info.items():
                    k = bytestostr(k)
                    pos = k.find("].encoder")
                    if k.startswith("window[") and pos>0:
                        wid_str = k[len("window["):pos]     #ie: "1"
                        ekey = k[(pos+len("].encoder")):]   #ie: "" or ".frames"
                        if ekey.startswith("."):
                            ekey = ekey[1:]
                        try:
                            wid = int(wid_str)
                            props = window_encoder_stats.setdefault(wid, {})
                            props[ekey] = v
                        except:
                            #wid_str may be invalid, ie:
                            #window[1].pipeline_option[1].encoder=codec_spec(xpra.codecs.enc_x264.encoder.Encoder)
                            # -> wid_str= "1].pipeline_option[1"
                            pass
                #print("window_encoder_stats=%s" % window_encoder_stats)
                for wid, props in window_encoder_stats.items():
                    l = label("%s (%s)" % (wid, props.get("")))
                    l.show()
                    info = ["%s=%s" % (k,v) for k,v in props.items() if k!=""]
                    set_tooltip_text(l, " ".join(info))
                    self.encoder_info_box.add(l)
        return True
示例#10
0
    def populate_statistics(self):
        log("populate_statistics()")
        if time.time()-self.last_populate_statistics<1.0:
            #don't repopulate more than every second
            return True
        self.last_populate_statistics = time.time()
        if self.client.server_info_request:
            self.client.send_info_request()
        def setall(labels, values):
            assert len(labels)==len(values), "%s labels and %s values (%s vs %s)" % (len(labels), len(values), labels, values)
            for i in range(len(labels)):
                l = labels[i]
                v = values[i]
                l.set_text(str(v))
        def setlabels(labels, values, rounding=int):
            if len(values)==0:
                return
            avg = sum(values)/len(values)
            svalues = sorted(values)
            l = len(svalues)
            assert l>0
            if l<10:
                index = l-1
            else:
                index = int(l*90/100)
            index = max(0, min(l-1, index))
            pct = svalues[index]
            disp = values[-1], min(values), avg, pct, max(values)
            rounded_values = [rounding(v) for v in disp]
            setall(labels, rounded_values)

        if len(self.client.server_ping_latency)>0:
            spl = [1000.0*x for _,x in list(self.client.server_ping_latency)]
            setlabels(self.server_latency_labels, spl)
        if len(self.client.client_ping_latency)>0:
            cpl = [1000.0*x for _,x in list(self.client.client_ping_latency)]
            setlabels(self.client_latency_labels, cpl)
        if self.client.windows_enabled:
            if self.client.server_info_request:
                setall(self.batch_labels, self.values_from_info("batch_delay", "batch.delay"))
                setall(self.damage_labels, self.values_from_info("damage_out_latency", "damage.out_latency"))
                setall(self.quality_labels, self.all_values_from_info("quality", "encoding.quality"))
                setall(self.speed_labels, self.all_values_from_info("speed", "encoding.speed"))

            region_sizes = []
            rps = []
            pps = []
            decoding_latency = []
            if len(self.client.pixel_counter)>0:
                min_time = None
                max_time = None
                regions_per_second = {}
                pixels_per_second = {}
                for start_time, end_time, size in self.client.pixel_counter:
                    decoding_latency.append(int(1000.0*(end_time-start_time)))
                    region_sizes.append(size)
                    if min_time is None or min_time>end_time:
                        min_time = end_time
                    if max_time is None or max_time<end_time:
                        max_time = end_time
                    time_in_seconds = int(end_time)
                    regions = regions_per_second.get(time_in_seconds, 0)
                    regions_per_second[time_in_seconds] = regions+1
                    pixels = pixels_per_second.get(time_in_seconds, 0)
                    pixels_per_second[time_in_seconds] = pixels + size
                if int(min_time)+1 < int(max_time):
                    for t in range(int(min_time)+1, int(max_time)):
                        rps.append(regions_per_second.get(t, 0))
                        pps.append(pixels_per_second.get(t, 0))
            setlabels(self.decoding_labels, decoding_latency)
            setlabels(self.regions_per_second_labels, rps)
            setlabels(self.regions_sizes_labels, region_sizes, rounding=std_unit_dec)
            setlabels(self.pixels_per_second_labels, pps, rounding=std_unit_dec)

            windows, gl, transient, trays = 0, 0, 0, 0
            for w in self.client._window_to_id.keys():
                if w.is_tray():
                    trays += 1
                elif w.is_OR():
                    transient +=1
                else:
                    windows += 1
                if w.is_GL():
                    gl += 1
            self.windows_managed_label.set_text(str(windows))
            self.transient_managed_label.set_text(str(transient))
            self.trays_managed_label.set_text(str(trays))
            if self.client.client_supports_opengl:
                self.opengl_label.set_text(str(gl))

            #remove all the current labels:
            for x in self.encoder_info_box.get_children():
                self.encoder_info_box.remove(x)
            window_encoder_stats = {}
            if self.client.server_last_info:
                #We are interested in data like:
                #window[1].encoder=x264
                #window[1].encoder.frames=1
                for k,v in self.client.server_last_info.items():
                    k = bytestostr(k)
                    pos = k.find("].encoder")
                    if k.startswith("window[") and pos>0:
                        wid_str = k[len("window["):pos]     #ie: "1"
                        ekey = k[(pos+len("].encoder")):]   #ie: "" or ".frames"
                        if ekey.startswith("."):
                            ekey = ekey[1:]
                        try:
                            wid = int(wid_str)
                            props = window_encoder_stats.setdefault(wid, {})
                            props[ekey] = v
                        except:
                            #wid_str may be invalid, ie:
                            #window[1].pipeline_option[1].encoder=codec_spec(xpra.codecs.enc_x264.encoder.Encoder)
                            # -> wid_str= "1].pipeline_option[1"
                            pass
                #print("window_encoder_stats=%s" % window_encoder_stats)
                for wid, props in window_encoder_stats.items():
                    l = label("%s (%s)" % (wid, bytestostr(props.get(""))))
                    l.show()
                    info = ["%s=%s" % (k,v) for k,v in props.items() if k!=""]
                    l.set_tooltip_text(" ".join(info))
                    self.encoder_info_box.add(l)
        return True
示例#11
0
 def maths_labels():
     return label(), label(), label(), label(), label()
示例#12
0
 def client_vinfo(prop, fallback="unknown"):
     k = "%s.version" % prop
     return label(make_version_str(gtk_version_info.get(k, fallback)))
示例#13
0
    def __init__(self, client, session_name, window_icon_pixbuf, conn, get_pixbuf):
        gtk.Window.__init__(self)
        self.client = client
        self.session_name = session_name
        self.connection = conn
        self.last_populate_time = 0
        self.last_populate_statistics = 0
        self.is_closed = False
        self.get_pixbuf = get_pixbuf
        if self.session_name == "Xpra":
            title = "Session Info"
        else:
            title = "%s: Session Info" % self.session_name
        self.set_title(title)
        self.set_destroy_with_parent(True)
        self.set_resizable(True)
        self.set_decorated(True)
        if window_icon_pixbuf:
            self.set_icon(window_icon_pixbuf)
        if is_gtk3():
            self.set_position(gtk.WindowPosition.CENTER)
        else:
            self.set_position(gtk.WIN_POS_CENTER)

        # tables on the left in a vbox with buttons at the top:
        self.tab_box = gtk.VBox(False, 0)
        self.tab_button_box = gtk.HBox(True, 0)
        self.tabs = []  # pairs of button, table
        self.populate_cb = None
        self.tab_box.pack_start(self.tab_button_box, expand=False, fill=True, padding=0)

        # Package Table:
        tb = self.table_tab("package.png", "Software", self.populate_package)
        # title row:
        tb.attach(title_box(""), 0, xoptions=gtk.EXPAND | gtk.FILL, xpadding=0)
        tb.attach(title_box("Client"), 1, xoptions=gtk.EXPAND | gtk.FILL, xpadding=0)
        tb.attach(title_box("Server"), 2, xoptions=gtk.EXPAND | gtk.FILL, xpadding=0)
        tb.inc()

        def make_os_str(sys_platform, platform_release, platform_platform, platform_linux_distribution):
            s = platform_name(sys_platform, platform_release)
            if (
                platform_linux_distribution
                and len(platform_linux_distribution) == 3
                and len(platform_linux_distribution[0]) > 0
            ):
                s += "\n%s" % (" ".join(platform_linux_distribution))
            elif platform_platform:
                s += "\n%s" % platform_platform
            return s

        LOCAL_PLATFORM_NAME = make_os_str(
            sys.platform, python_platform.release(), python_platform.platform(), python_platform.linux_distribution()
        )
        SERVER_PLATFORM_NAME = make_os_str(
            self.client._remote_platform,
            self.client._remote_platform_release,
            self.client._remote_platform_platform,
            self.client._remote_platform_linux_distribution,
        )
        tb.new_row("Operating System", label(LOCAL_PLATFORM_NAME), label(SERVER_PLATFORM_NAME))
        scaps = self.client.server_capabilities
        from xpra.__init__ import __version__

        tb.new_row("Xpra", label(__version__), label(self.client._remote_version or "unknown"))
        cl_rev, cl_ch, cl_date = "unknown", "", ""
        try:
            from xpra.build_info import BUILD_DATE as cl_date
            from xpra.src_info import REVISION as cl_rev, LOCAL_MODIFICATIONS as cl_ch
        except:
            pass

        def make_version_str(version):
            if version and type(version) in (tuple, list):
                version = ".".join([str(x) for x in version])
            return version or "unknown"

        def server_info(*prop_names):
            for x in prop_names:
                v = scaps.get(x)
                if v is not None:
                    return v
            return None

        def server_version_info(*prop_names):
            return make_version_str(server_info(*prop_names))

        tb.new_row("Revision", label(cl_rev), label(make_version_str(self.client._remote_revision)))
        tb.new_row(
            "Local Changes",
            label(cl_ch),
            label(server_version_info("build.local_modifications", "local_modifications")),
        )
        tb.new_row("Build date", label(cl_date), label(server_info("build_date", "build.date")))

        def client_version_info(prop_name):
            info = "unknown"
            if hasattr(gtk, prop_name):
                info = make_version_str(getattr(gtk, prop_name))
            return info

        if is_gtk3():
            tb.new_row("PyGobject", label(gobject._version))
            tb.new_row("Client GDK", label(gdk._version))
            tb.new_row("GTK", label(gtk._version), label(server_version_info("gtk_version")))
        else:
            tb.new_row(
                "PyGTK",
                label(client_version_info("pygtk_version")),
                label(server_version_info("pygtk.version", "pygtk_version")),
            )
            tb.new_row(
                "GTK",
                label(client_version_info("gtk_version")),
                label(server_version_info("gtk.version", "gtk_version")),
            )
        tb.new_row(
            "Python",
            label(python_platform.python_version()),
            label(server_version_info("server.python.version", "python_version")),
        )
        cl_gst_v, cl_pygst_v = "", ""
        if HAS_SOUND:
            try:
                from xpra.sound.gstreamer_util import gst_version as cl_gst_v, pygst_version as cl_pygst_v
            except:
                pass
        tb.new_row(
            "GStreamer",
            label(make_version_str(cl_gst_v)),
            label(server_version_info("sound.gst.version", "gst_version")),
        )
        tb.new_row(
            "pygst",
            label(make_version_str(cl_pygst_v)),
            label(server_version_info("sound.pygst.version", "pygst_version")),
        )
        tb.new_row("OpenGL", label(make_version_str(self.client.opengl_props.get("opengl", "n/a"))), label("n/a"))
        tb.new_row("OpenGL Vendor", label(make_version_str(self.client.opengl_props.get("vendor", ""))), label("n/a"))
        tb.new_row("PyOpenGL", label(make_version_str(self.client.opengl_props.get("pyopengl", "n/a"))), label("n/a"))

        # Features Table:
        tb = self.table_tab("features.png", "Features", self.populate_features)
        randr_box = gtk.HBox(False, 20)
        self.server_randr_label = label()
        self.server_randr_icon = gtk.Image()
        randr_box.add(self.server_randr_icon)
        randr_box.add(self.server_randr_label)
        tb.new_row("RandR Support", randr_box)
        opengl_box = gtk.HBox(False, 20)
        self.client_opengl_label = label()
        self.client_opengl_label.set_line_wrap(True)
        self.client_opengl_icon = gtk.Image()
        opengl_box.add(self.client_opengl_icon)
        opengl_box.add(self.client_opengl_label)
        tb.new_row("Client OpenGL", opengl_box)
        self.opengl_buffering = label()
        tb.new_row("OpenGL Buffering", self.opengl_buffering)
        self.server_encodings_label = label()
        tb.new_row("Server Encodings", self.server_encodings_label)
        self.client_encodings_label = label()
        tb.new_row("Client Encodings", self.client_encodings_label)
        self.server_mmap_icon = gtk.Image()
        tb.new_row("Memory Mapped Transfers", self.server_mmap_icon)
        self.server_clipboard_icon = gtk.Image()
        tb.new_row("Clipboard", self.server_clipboard_icon)
        self.server_notifications_icon = gtk.Image()
        tb.new_row("Notification Forwarding", self.server_notifications_icon)
        self.server_bell_icon = gtk.Image()
        tb.new_row("Bell Forwarding", self.server_bell_icon)
        self.server_cursors_icon = gtk.Image()
        tb.new_row("Cursor Forwarding", self.server_cursors_icon)
        speaker_box = gtk.HBox(False, 20)
        self.server_speaker_icon = gtk.Image()
        speaker_box.add(self.server_speaker_icon)
        self.speaker_codec_label = label()
        speaker_box.add(self.speaker_codec_label)
        tb.new_row("Speaker Forwarding", speaker_box)
        self.server_speaker_codecs_label = label()
        tb.new_row("Server Codecs", self.server_speaker_codecs_label)
        self.client_speaker_codecs_label = label()
        tb.new_row("Client Codecs", self.client_speaker_codecs_label)
        microphone_box = gtk.HBox(False, 20)
        self.server_microphone_icon = gtk.Image()
        microphone_box.add(self.server_microphone_icon)
        self.microphone_codec_label = label()
        microphone_box.add(self.microphone_codec_label)
        tb.new_row("Microphone Forwarding", microphone_box)
        self.server_microphone_codecs_label = label()
        tb.new_row("Server Codecs", self.server_microphone_codecs_label)
        self.client_microphone_codecs_label = label()
        tb.new_row("Client Codecs", self.client_microphone_codecs_label)

        # Connection Table:
        tb = self.table_tab("connect.png", "Connection", self.populate_connection)
        tb.new_row("Server Endpoint", label(self.connection.target))
        if self.client.server_display:
            tb.new_row("Server Display", label(self.client.server_display))
        if "hostname" in scaps:
            tb.new_row("Server Hostname", label(scaps.get("hostname")))
        if self.client.server_platform:
            tb.new_row("Server Platform", label(self.client.server_platform))
        self.server_load_label = label()
        tb.new_row("Server Load", self.server_load_label, label_tooltip="Average over 1, 5 and 15 minutes")
        self.session_started_label = label()
        tb.new_row("Session Started", self.session_started_label)
        self.session_connected_label = label()
        tb.new_row("Session Connected", self.session_connected_label)
        self.input_packets_label = label()
        tb.new_row("Packets Received", self.input_packets_label)
        self.input_bytes_label = label()
        tb.new_row("Bytes Received", self.input_bytes_label)
        self.output_packets_label = label()
        tb.new_row("Packets Sent", self.output_packets_label)
        self.output_bytes_label = label()
        tb.new_row("Bytes Sent", self.output_bytes_label)
        self.compression_label = label()
        tb.new_row("Compression Level", self.compression_label)
        self.connection_type_label = label()
        tb.new_row("Connection Type", self.connection_type_label)
        self.input_encryption_label = label()
        tb.new_row("Input Encryption", self.input_encryption_label)
        self.output_encryption_label = label()
        tb.new_row("Output Encryption", self.output_encryption_label)

        self.speaker_label = label()
        self.speaker_details = label(font="monospace 10")
        tb.new_row("Speaker", self.speaker_label, self.speaker_details)
        self.microphone_label = label()
        tb.new_row("Microphone", self.microphone_label)

        # Details:
        tb = self.table_tab("browse.png", "Statistics", self.populate_statistics)
        tb.widget_xalign = 1.0
        tb.attach(title_box(""), 0, xoptions=gtk.EXPAND | gtk.FILL, xpadding=0)
        tb.attach(title_box("Latest"), 1, xoptions=gtk.EXPAND | gtk.FILL, xpadding=0)
        tb.attach(title_box("Minimum"), 2, xoptions=gtk.EXPAND | gtk.FILL, xpadding=0)
        tb.attach(title_box("Average"), 3, xoptions=gtk.EXPAND | gtk.FILL, xpadding=0)
        tb.attach(title_box("90 percentile"), 4, xoptions=gtk.EXPAND | gtk.FILL, xpadding=0)
        tb.attach(title_box("Maximum"), 5, xoptions=gtk.EXPAND | gtk.FILL, xpadding=0)
        tb.inc()

        def maths_labels():
            return label(), label(), label(), label(), label()

        self.server_latency_labels = maths_labels()
        tb.add_row(label("Server Latency (ms)"), *self.server_latency_labels)
        self.client_latency_labels = maths_labels()
        tb.add_row(label("Client Latency (ms)"), *self.client_latency_labels)
        if self.client.windows_enabled:
            if self.client.server_info_request:
                self.batch_labels = maths_labels()
                tb.add_row(label("Batch Delay (ms)"), *self.batch_labels)
                self.damage_labels = maths_labels()
                tb.add_row(label("Damage Latency (ms)"), *self.damage_labels)
                self.quality_labels = maths_labels()
                tb.add_row(label("Encoding Quality (pct)"), *self.quality_labels)
                self.speed_labels = maths_labels()
                tb.add_row(label("Encoding Speed (pct)"), *self.speed_labels)

            self.decoding_labels = maths_labels()
            tb.add_row(label("Decoding Latency (ms)"), *self.decoding_labels)
            self.regions_per_second_labels = maths_labels()
            tb.add_row(label("Regions/s"), *self.regions_per_second_labels)
            self.regions_sizes_labels = maths_labels()
            tb.add_row(label("Pixels/region"), *self.regions_sizes_labels)
            self.pixels_per_second_labels = maths_labels()
            tb.add_row(label("Pixels/s"), *self.pixels_per_second_labels)

            self.windows_managed_label = label()
            tb.new_row("Regular Windows", self.windows_managed_label),
            self.transient_managed_label = label()
            tb.new_row("Transient Windows", self.transient_managed_label),
            self.trays_managed_label = label()
            tb.new_row("Trays Managed", self.trays_managed_label),
            if self.client.client_supports_opengl:
                self.opengl_label = label()
                tb.new_row("OpenGL Windows", self.opengl_label),

        self.graph_box = gtk.VBox(False, 10)
        self.add_tab("statistics.png", "Graphs", self.populate_graphs, self.graph_box)
        bandwidth_label = "Number of bytes measured by the networks sockets"
        if SHOW_PIXEL_STATS:
            bandwidth_label += ",\nand number of pixels rendered"
        self.bandwidth_graph = self.add_graph_button(bandwidth_label, self.save_graphs)
        self.latency_graph = self.add_graph_button(
            "The time it takes to send an echo packet and get the reply", self.save_graphs
        )
        self.pixel_in_data = maxdeque(N_SAMPLES + 4)
        self.net_in_bytecount = maxdeque(N_SAMPLES + 4)
        self.net_out_bytecount = maxdeque(N_SAMPLES + 4)

        self.set_border_width(15)
        self.add(self.tab_box)
        if not is_gtk3():
            self.set_geometry_hints(self.tab_box)

        def window_deleted(*args):
            self.is_closed = True

        self.connect("delete_event", window_deleted)
        self.show_tab(self.tabs[0][1])
        self.set_size_request(-1, 480)
        self.populate()
        self.populate_all()
        gobject.timeout_add(1000, self.populate)
        gobject.timeout_add(100, self.populate_tab)
        self.connect("realize", self.populate_graphs)
        add_close_accel(self, self.destroy)
示例#14
0
 def maths_labels():
     return label(), label(), label(), label(), label()
示例#15
0
class SessionInfo(gtk.Window):

    def __init__(self, client, session_name, window_icon_pixbuf, conn, get_pixbuf):
        gtk.Window.__init__(self)
        self.client = client
        self.session_name = session_name
        self.connection = conn
        self.last_populate_time = 0
        self.last_populate_statistics = 0
        self.is_closed = False
        self.get_pixbuf = get_pixbuf
        if not self.session_name or self.session_name=="Xpra":
            title = "Session Info"
        else:
            title = "%s: Session Info" % self.session_name
        self.set_title(title)
        self.set_destroy_with_parent(True)
        self.set_resizable(True)
        self.set_decorated(True)
        if window_icon_pixbuf:
            self.set_icon(window_icon_pixbuf)
        self.set_position(WIN_POS_CENTER)

        #tables on the left in a vbox with buttons at the top:
        self.tab_box = gtk.VBox(False, 0)
        self.tab_button_box = gtk.HBox(True, 0)
        self.tabs = []          #pairs of button, table
        self.populate_cb = None
        self.tab_box.pack_start(self.tab_button_box, expand=False, fill=True, padding=0)

        #Package Table:
        tb, _ = self.table_tab("package.png", "Software", self.populate_package)
        #title row:
        tb.attach(title_box(""), 0, xoptions=EXPAND|FILL, xpadding=0)
        tb.attach(title_box("Client"), 1, xoptions=EXPAND|FILL, xpadding=0)
        tb.attach(title_box("Server"), 2, xoptions=EXPAND|FILL, xpadding=0)
        tb.inc()

        def make_os_str(*args):
            s = os_info(*args)
            return "\n".join(s)
        distro = ""
        if hasattr(python_platform, "linux_distribution"):
            distro = python_platform.linux_distribution()
        LOCAL_PLATFORM_NAME = make_os_str(sys.platform, python_platform.release(), python_platform.platform(), distro)
        SERVER_PLATFORM_NAME = make_os_str(self.client._remote_platform, self.client._remote_platform_release, self.client._remote_platform_platform, self.client._remote_platform_linux_distribution)
        tb.new_row("Operating System", label(LOCAL_PLATFORM_NAME), label(SERVER_PLATFORM_NAME))
        scaps = self.client.server_capabilities
        from xpra.__init__ import __version__
        tb.new_row("Xpra", label(__version__), label(self.client._remote_version or "unknown"))
        cl_rev, cl_ch, cl_date = "unknown", "", ""
        try:
            from xpra.build_info import BUILD_DATE as cl_date, BUILD_TIME as cl_time
            from xpra.src_info import REVISION as cl_rev, LOCAL_MODIFICATIONS as cl_ch      #@UnresolvedImport
        except:
            pass
        def make_version_str(version):
            if version and type(version) in (tuple, list):
                version = ".".join([str(x) for x in version])
            return version or "unknown"
        def server_info(*prop_names):
            for x in prop_names:
                v = scaps.capsget(x)
                if v is not None:
                    return v
                if self.client.server_last_info:
                    v = self.client.server_last_info.get(x)
                if v is not None:
                    return v
            return None
        def server_version_info(*prop_names):
            return make_version_str(server_info(*prop_names))
        def make_revision_str(rev, changes):
            if not changes:
                return rev
            return "%s (%s changes)" % (rev, changes)
        def make_datetime(date, time):
            if not time:
                return date
            return "%s %s" % (date, time)
        tb.new_row("Revision", label(make_revision_str(cl_rev, cl_ch)),
                               label(make_revision_str(self.client._remote_revision, server_version_info("build.local_modifications", "local_modifications"))))
        tb.new_row("Build date", label(make_datetime(cl_date, cl_time)),
                                 label(make_datetime(server_info("build_date", "build.date"), server_info("build.time"))))
        gtk_version_info = get_gtk_version_info()
        def client_vinfo(prop, fallback="unknown"):
            k = "%s.version" % prop
            return label(make_version_str(gtk_version_info.get(k, fallback)))
        tb.new_row("Glib",      client_vinfo("glib"),       label(server_version_info("glib.version")))
        tb.new_row("Gobject",   client_vinfo("gobject"),    label(server_version_info("gobject.version", "pygtk_version")))
        tb.new_row("PyGTK",     client_vinfo("pygtk", ""),  label(server_version_info("pygtk.version", "pygtk_version")))
        tb.new_row("GTK",       client_vinfo("gtk"),        label(server_version_info("gtk.version", "gtk_version")))
        tb.new_row("GDK",       client_vinfo("gdk"),        label(server_version_info("gdk.version", "gdk_version")))
        tb.new_row("Cairo",     client_vinfo("cairo"),      label(server_version_info("cairo.version", "cairo_version")))
        tb.new_row("Pango",     client_vinfo("pango"),      label(server_version_info("pango.version", "cairo_version")))
        tb.new_row("Python", label(python_platform.python_version()), label(server_version_info("server.python.version", "python_version", "python.version")))

        cl_gst_v, cl_pygst_v = "", ""
        try:
            from xpra.sound.gstreamer_util import gst_version as cl_gst_v, pygst_version as cl_pygst_v
        except Exception, e:
            log("cannot load gstreamer: %s", e)
        tb.new_row("GStreamer", label(make_version_str(cl_gst_v)), label(server_version_info("sound.gst.version", "gst_version")))
        tb.new_row("pygst", label(make_version_str(cl_pygst_v)), label(server_version_info("sound.pygst.version", "pygst_version")))
        tb.new_row("OpenGL", label(make_version_str(self.client.opengl_props.get("opengl", "n/a"))), label("n/a"))
        tb.new_row("OpenGL Vendor", label(make_version_str(self.client.opengl_props.get("vendor", ""))), label("n/a"))
        tb.new_row("PyOpenGL", label(make_version_str(self.client.opengl_props.get("pyopengl", "n/a"))), label("n/a"))

        # Features Table:
        vbox = self.vbox_tab("features.png", "Features", self.populate_features)
        #add top table:
        tb = TableBuilder(rows=1, columns=2)
        table = tb.get_table()
        al = gtk.Alignment(xalign=0.5, yalign=0.5, xscale=0.0, yscale=1.0)
        al.add(table)
        vbox.pack_start(al, expand=True, fill=False, padding=10)
        #top table contents:
        randr_box = gtk.HBox(False, 20)
        self.server_randr_label = label()
        self.server_randr_icon = gtk.Image()
        randr_box.add(self.server_randr_icon)
        randr_box.add(self.server_randr_label)
        tb.new_row("RandR Support", randr_box)
        opengl_box = gtk.HBox(False, 20)
        self.client_opengl_label = label()
        self.client_opengl_label.set_line_wrap(True)
        self.client_opengl_icon = gtk.Image()
        opengl_box.add(self.client_opengl_icon)
        opengl_box.add(self.client_opengl_label)
        tb.new_row("Client OpenGL", opengl_box)
        self.opengl_buffering = label()
        tb.new_row("OpenGL Buffering", self.opengl_buffering)
        self.server_mmap_icon = gtk.Image()
        tb.new_row("Memory Mapped Transfers", self.server_mmap_icon)
        self.server_clipboard_icon = gtk.Image()
        tb.new_row("Clipboard", self.server_clipboard_icon)
        self.server_notifications_icon = gtk.Image()
        tb.new_row("Notification Forwarding", self.server_notifications_icon)
        self.server_bell_icon = gtk.Image()
        tb.new_row("Bell Forwarding", self.server_bell_icon)
        self.server_cursors_icon = gtk.Image()
        tb.new_row("Cursor Forwarding", self.server_cursors_icon)
        speaker_box = gtk.HBox(False, 20)
        self.server_speaker_icon = gtk.Image()
        speaker_box.add(self.server_speaker_icon)
        self.speaker_codec_label = label()
        speaker_box.add(self.speaker_codec_label)
        tb.new_row("Speaker Forwarding", speaker_box)
        microphone_box = gtk.HBox(False, 20)
        self.server_microphone_icon = gtk.Image()
        microphone_box.add(self.server_microphone_icon)
        self.microphone_codec_label = label()
        microphone_box.add(self.microphone_codec_label)
        tb.new_row("Microphone Forwarding", microphone_box)
        #add bottom table:
        tb = TableBuilder(rows=1, columns=3)
        table = tb.get_table()
        vbox.pack_start(table, expand=True, fill=True, padding=20)
        #bottom table headings:
        tb.attach(title_box(""), 0, xoptions=EXPAND|FILL, xpadding=0)
        tb.attach(title_box("Client"), 1, xoptions=EXPAND|FILL, xpadding=0)
        tb.attach(title_box("Server"), 2, xoptions=EXPAND|FILL, xpadding=0)
        tb.inc()
        #bottom table contents:
        self.client_encodings_label = label()
        self.client_encodings_label.set_line_wrap(True)
        self.client_encodings_label.set_size_request(250, -1)
        self.server_encodings_label = label()
        self.server_encodings_label.set_line_wrap(True)
        self.server_encodings_label.set_size_request(250, -1)
        tb.new_row("Encodings", self.client_encodings_label, self.server_encodings_label)
        self.client_speaker_codecs_label = label()
        self.server_speaker_codecs_label = label()
        tb.new_row("Speaker Codecs", self.client_speaker_codecs_label, self.server_speaker_codecs_label)
        self.client_microphone_codecs_label = label()
        self.server_microphone_codecs_label = label()
        tb.new_row("Microphone Codecs", self.client_microphone_codecs_label, self.server_microphone_codecs_label)
        self.client_packet_encoders_label = label()
        self.server_packet_encoders_label = label()
        tb.new_row("Packet Encoders", self.client_packet_encoders_label, self.server_packet_encoders_label)
        self.client_packet_compressors_label = label()
        self.server_packet_compressors_label = label()
        tb.new_row("Packet Compressors", self.client_packet_compressors_label, self.server_packet_compressors_label)

        # Connection Table:
        tb, _ = self.table_tab("connect.png", "Connection", self.populate_connection)
        tb.new_row("Server Endpoint", label(self.connection.target))
        if self.client.server_display:
            tb.new_row("Server Display", label(self.client.server_display))
        hostname = scaps.strget("hostname")
        if hostname:
            tb.new_row("Server Hostname", label(hostname))
        if self.client.server_platform:
            tb.new_row("Server Platform", label(self.client.server_platform))
        self.server_load_label = label()
        tb.new_row("Server Load", self.server_load_label, label_tooltip="Average over 1, 5 and 15 minutes")
        self.session_started_label = label()
        tb.new_row("Session Started", self.session_started_label)
        self.session_connected_label = label()
        tb.new_row("Session Connected", self.session_connected_label)
        self.input_packets_label = label()
        tb.new_row("Packets Received", self.input_packets_label)
        self.input_bytes_label = label()
        tb.new_row("Bytes Received", self.input_bytes_label)
        self.output_packets_label = label()
        tb.new_row("Packets Sent", self.output_packets_label)
        self.output_bytes_label = label()
        tb.new_row("Bytes Sent", self.output_bytes_label)
        self.compression_label = label()
        tb.new_row("Compression + Encoding", self.compression_label)
        self.connection_type_label = label()
        tb.new_row("Connection Type", self.connection_type_label)
        self.input_encryption_label = label()
        tb.new_row("Input Encryption", self.input_encryption_label)
        self.output_encryption_label = label()
        tb.new_row("Output Encryption", self.output_encryption_label)

        self.speaker_label = label()
        self.speaker_details = label(font="monospace 10")
        tb.new_row("Speaker", self.speaker_label, self.speaker_details)
        self.microphone_label = label()
        tb.new_row("Microphone", self.microphone_label)

        # Details:
        tb, stats_box = self.table_tab("browse.png", "Statistics", self.populate_statistics)
        tb.widget_xalign = 1.0
        tb.attach(title_box(""), 0, xoptions=EXPAND|FILL, xpadding=0)
        tb.attach(title_box("Latest"), 1, xoptions=EXPAND|FILL, xpadding=0)
        tb.attach(title_box("Minimum"), 2, xoptions=EXPAND|FILL, xpadding=0)
        tb.attach(title_box("Average"), 3, xoptions=EXPAND|FILL, xpadding=0)
        tb.attach(title_box("90 percentile"), 4, xoptions=EXPAND|FILL, xpadding=0)
        tb.attach(title_box("Maximum"), 5, xoptions=EXPAND|FILL, xpadding=0)
        tb.inc()

        def maths_labels():
            return label(), label(), label(), label(), label()
        self.server_latency_labels = maths_labels()
        tb.add_row(label("Server Latency (ms)", "The time it takes for the server to respond to pings"),
                   *self.server_latency_labels)
        self.client_latency_labels = maths_labels()
        tb.add_row(label("Client Latency (ms)", "The time it takes for the client to respond to pings, as measured by the server"),
                   *self.client_latency_labels)
        if self.client.windows_enabled:
            if self.client.server_info_request:
                self.batch_labels = maths_labels()
                tb.add_row(label("Batch Delay (ms)", "How long the server waits for new screen updates to accumulate before processing them"),
                           *self.batch_labels)
                self.damage_labels = maths_labels()
                tb.add_row(label("Damage Latency (ms)", "The time it takes to compress a frame and pass it to the OS network layer"),
                           *self.damage_labels)
                self.quality_labels = maths_labels()
                tb.add_row(label("Encoding Quality (pct)"), *self.quality_labels)
                self.speed_labels = maths_labels()
                tb.add_row(label("Encoding Speed (pct)"), *self.speed_labels)

            self.decoding_labels = maths_labels()
            tb.add_row(label("Decoding Latency (ms)", "How long it takes the client to decode a screen update"), *self.decoding_labels)
            self.regions_per_second_labels = maths_labels()
            tb.add_row(label("Regions/s", "The number of screen updates per second (includes both partial and full screen updates)"), *self.regions_per_second_labels)
            self.regions_sizes_labels = maths_labels()
            tb.add_row(label("Pixels/region", "The number of pixels per screen update"), *self.regions_sizes_labels)
            self.pixels_per_second_labels = maths_labels()
            tb.add_row(label("Pixels/s", "The number of pixels processed per second"), *self.pixels_per_second_labels)

            #Window count stats:
            wtb = TableBuilder()
            stats_box.add(wtb.get_table())
            #title row:
            wtb.attach(title_box(""), 0, xoptions=EXPAND|FILL, xpadding=0)
            wtb.attach(title_box("Regular"), 1, xoptions=EXPAND|FILL, xpadding=0)
            wtb.attach(title_box("Transient"), 2, xoptions=EXPAND|FILL, xpadding=0)
            wtb.attach(title_box("Trays"), 3, xoptions=EXPAND|FILL, xpadding=0)
            if self.client.client_supports_opengl:
                wtb.attach(title_box("OpenGL"), 4, xoptions=EXPAND|FILL, xpadding=0)
            wtb.inc()

            wtb.attach(label("Windows:"), 0, xoptions=EXPAND|FILL, xpadding=0)
            self.windows_managed_label = label()
            wtb.attach(self.windows_managed_label, 1)
            self.transient_managed_label = label()
            wtb.attach(self.transient_managed_label, 2)
            self.trays_managed_label = label()
            wtb.attach(self.trays_managed_label, 3)
            if self.client.client_supports_opengl:
                self.opengl_label = label()
                wtb.attach(self.opengl_label, 4)

            #add encoder info:
            etb = TableBuilder()
            stats_box.add(etb.get_table())
            self.encoder_info_box = gtk.HBox(spacing=4)
            etb.new_row("Window Encoders", self.encoder_info_box)

        if not is_gtk3():
            #needs porting to cairo...
            self.graph_box = gtk.VBox(False, 10)
            self.add_tab("statistics.png", "Graphs", self.populate_graphs, self.graph_box)
            bandwidth_label = "Bandwidth used"
            if SHOW_PIXEL_STATS:
                bandwidth_label += ",\nand number of pixels rendered"
            self.bandwidth_graph = self.add_graph_button(bandwidth_label, self.save_graphs)
            self.connect("realize", self.populate_graphs)
            self.latency_graph = self.add_graph_button(None, self.save_graphs)
        self.pixel_in_data = maxdeque(N_SAMPLES+4)
        self.net_in_bytecount = maxdeque(N_SAMPLES+4)
        self.net_out_bytecount = maxdeque(N_SAMPLES+4)

        self.set_border_width(15)
        self.add(self.tab_box)
        if not is_gtk3():
            self.set_geometry_hints(self.tab_box)
        def window_deleted(*args):
            self.is_closed = True
        self.connect('delete_event', window_deleted)
        self.show_tab(self.tabs[0][2])
        self.set_size_request(-1, 480)
        self.init_counters()
        self.populate()
        self.populate_all()
        gobject.timeout_add(1000, self.populate)
        gobject.timeout_add(100, self.populate_tab)
        add_close_accel(self, self.destroy)
示例#16
0
    def __init__(self, client, session_name, window_icon_pixbuf, conn, get_pixbuf):
        gtk.Window.__init__(self)
        self.client = client
        self.session_name = session_name
        self.connection = conn
        self.last_populate_time = 0
        self.last_populate_statistics = 0
        self.is_closed = False
        self.get_pixbuf = get_pixbuf
        if not self.session_name or self.session_name=="Xpra":
            title = "Session Info"
        else:
            title = "%s: Session Info" % self.session_name
        self.set_title(title)
        self.set_destroy_with_parent(True)
        self.set_resizable(True)
        self.set_decorated(True)
        if window_icon_pixbuf:
            self.set_icon(window_icon_pixbuf)
        self.set_position(WIN_POS_CENTER)

        #tables on the left in a vbox with buttons at the top:
        self.tab_box = gtk.VBox(False, 0)
        self.tab_button_box = gtk.HBox(True, 0)
        self.tabs = []          #pairs of button, table
        self.populate_cb = None
        self.tab_box.pack_start(self.tab_button_box, expand=False, fill=True, padding=0)

        #Package Table:
        tb, _ = self.table_tab("package.png", "Software", self.populate_package)
        #title row:
        tb.attach(title_box(""), 0, xoptions=EXPAND|FILL, xpadding=0)
        tb.attach(title_box("Client"), 1, xoptions=EXPAND|FILL, xpadding=0)
        tb.attach(title_box("Server"), 2, xoptions=EXPAND|FILL, xpadding=0)
        tb.inc()

        def make_os_str(*args):
            s = os_info(*args)
            return "\n".join(s)
        distro = ""
        if hasattr(python_platform, "linux_distribution"):
            distro = python_platform.linux_distribution()
        LOCAL_PLATFORM_NAME = make_os_str(sys.platform, python_platform.release(), python_platform.platform(), distro)
        SERVER_PLATFORM_NAME = make_os_str(self.client._remote_platform, self.client._remote_platform_release, self.client._remote_platform_platform, self.client._remote_platform_linux_distribution)
        tb.new_row("Operating System", label(LOCAL_PLATFORM_NAME), label(SERVER_PLATFORM_NAME))
        scaps = self.client.server_capabilities
        from xpra.__init__ import __version__
        tb.new_row("Xpra", label(__version__), label(self.client._remote_version or "unknown"))
        cl_rev, cl_ch, cl_date = "unknown", "", ""
        try:
            from xpra.build_info import BUILD_DATE as cl_date, BUILD_TIME as cl_time
            from xpra.src_info import REVISION as cl_rev, LOCAL_MODIFICATIONS as cl_ch      #@UnresolvedImport
        except:
            pass
        def make_version_str(version):
            if version and type(version) in (tuple, list):
                version = ".".join([str(x) for x in version])
            return version or "unknown"
        def server_info(*prop_names):
            for x in prop_names:
                v = scaps.capsget(x)
                if v is not None:
                    return v
                if self.client.server_last_info:
                    v = self.client.server_last_info.get(x)
                if v is not None:
                    return v
            return None
        def server_version_info(*prop_names):
            return make_version_str(server_info(*prop_names))
        def make_revision_str(rev, changes):
            if not changes:
                return rev
            return "%s (%s changes)" % (rev, changes)
        def make_datetime(date, time):
            if not time:
                return date
            return "%s %s" % (date, time)
        tb.new_row("Revision", label(make_revision_str(cl_rev, cl_ch)),
                               label(make_revision_str(self.client._remote_revision, server_version_info("build.local_modifications", "local_modifications"))))
        tb.new_row("Build date", label(make_datetime(cl_date, cl_time)),
                                 label(make_datetime(server_info("build_date", "build.date"), server_info("build.time"))))
        gtk_version_info = get_gtk_version_info()
        def client_vinfo(prop, fallback="unknown"):
            k = "%s.version" % prop
            return label(make_version_str(gtk_version_info.get(k, fallback)))
        def server_vinfo(prop):
            k = "%s.version" % prop
            fk = "%s_version" % prop
            return label(server_version_info(k, fk))
        tb.new_row("Glib",      client_vinfo("glib"),       server_vinfo("glib"))
        tb.new_row("PyGlib",    client_vinfo("pyglib"),     server_vinfo("pyglib"))
        tb.new_row("Gobject",   client_vinfo("gobject"),    server_vinfo("gobject"))
        tb.new_row("PyGTK",     client_vinfo("pygtk", ""),  server_vinfo("pygtk"))
        tb.new_row("GTK",       client_vinfo("gtk"),        server_vinfo("gtk"))
        tb.new_row("GDK",       client_vinfo("gdk"),        server_vinfo("gdk"))
        tb.new_row("Cairo",     client_vinfo("cairo"),      server_vinfo("cairo"))
        tb.new_row("Pango",     client_vinfo("pango"),      server_vinfo("pango"))
        tb.new_row("Python", label(python_platform.python_version()), label(server_version_info("server.python.version", "python_version", "python.version")))

        cl_gst_v, cl_pygst_v = "", ""
        try:
            from xpra.sound.gstreamer_util import gst_version as cl_gst_v, pygst_version as cl_pygst_v
        except Exception as e:
            log("cannot load gstreamer: %s", e)
        tb.new_row("GStreamer", label(make_version_str(cl_gst_v)), label(server_version_info("sound.gst.version", "gst_version")))
        tb.new_row("pygst", label(make_version_str(cl_pygst_v)), label(server_version_info("sound.pygst.version", "pygst_version")))
        tb.new_row("OpenGL", label(make_version_str(self.client.opengl_props.get("opengl", "n/a"))), label("n/a"))
        tb.new_row("OpenGL Vendor", label(make_version_str(self.client.opengl_props.get("vendor", ""))), label("n/a"))
        tb.new_row("PyOpenGL", label(make_version_str(self.client.opengl_props.get("pyopengl", "n/a"))), label("n/a"))

        # Features Table:
        vbox = self.vbox_tab("features.png", "Features", self.populate_features)
        #add top table:
        tb = TableBuilder(rows=1, columns=2)
        table = tb.get_table()
        al = gtk.Alignment(xalign=0.5, yalign=0.5, xscale=0.0, yscale=1.0)
        al.add(table)
        vbox.pack_start(al, expand=True, fill=False, padding=10)
        #top table contents:
        randr_box = gtk.HBox(False, 20)
        self.server_randr_label = label()
        self.server_randr_icon = gtk.Image()
        randr_box.add(self.server_randr_icon)
        randr_box.add(self.server_randr_label)
        tb.new_row("RandR Support", randr_box)
        opengl_box = gtk.HBox(False, 20)
        self.client_opengl_label = label()
        self.client_opengl_label.set_line_wrap(True)
        self.client_opengl_icon = gtk.Image()
        opengl_box.add(self.client_opengl_icon)
        opengl_box.add(self.client_opengl_label)
        tb.new_row("Client OpenGL", opengl_box)
        self.opengl_buffering = label()
        tb.new_row("OpenGL Buffering", self.opengl_buffering)
        self.server_mmap_icon = gtk.Image()
        tb.new_row("Memory Mapped Transfers", self.server_mmap_icon)
        self.server_clipboard_icon = gtk.Image()
        tb.new_row("Clipboard", self.server_clipboard_icon)
        self.server_notifications_icon = gtk.Image()
        tb.new_row("Notification Forwarding", self.server_notifications_icon)
        self.server_bell_icon = gtk.Image()
        tb.new_row("Bell Forwarding", self.server_bell_icon)
        self.server_cursors_icon = gtk.Image()
        tb.new_row("Cursor Forwarding", self.server_cursors_icon)
        speaker_box = gtk.HBox(False, 20)
        self.server_speaker_icon = gtk.Image()
        speaker_box.add(self.server_speaker_icon)
        self.speaker_codec_label = label()
        speaker_box.add(self.speaker_codec_label)
        tb.new_row("Speaker Forwarding", speaker_box)
        microphone_box = gtk.HBox(False, 20)
        self.server_microphone_icon = gtk.Image()
        microphone_box.add(self.server_microphone_icon)
        self.microphone_codec_label = label()
        microphone_box.add(self.microphone_codec_label)
        tb.new_row("Microphone Forwarding", microphone_box)
        #add bottom table:
        tb = TableBuilder(rows=1, columns=3)
        table = tb.get_table()
        vbox.pack_start(table, expand=True, fill=True, padding=20)
        #bottom table headings:
        tb.attach(title_box(""), 0, xoptions=EXPAND|FILL, xpadding=0)
        tb.attach(title_box("Client"), 1, xoptions=EXPAND|FILL, xpadding=0)
        tb.attach(title_box("Server"), 2, xoptions=EXPAND|FILL, xpadding=0)
        tb.inc()
        #bottom table contents:
        self.client_encodings_label = label()
        self.client_encodings_label.set_line_wrap(True)
        self.client_encodings_label.set_size_request(250, -1)
        self.server_encodings_label = label()
        self.server_encodings_label.set_line_wrap(True)
        self.server_encodings_label.set_size_request(250, -1)
        tb.new_row("Encodings", self.client_encodings_label, self.server_encodings_label)
        self.client_speaker_codecs_label = label()
        self.server_speaker_codecs_label = label()
        tb.new_row("Speaker Codecs", self.client_speaker_codecs_label, self.server_speaker_codecs_label)
        self.client_microphone_codecs_label = label()
        self.server_microphone_codecs_label = label()
        tb.new_row("Microphone Codecs", self.client_microphone_codecs_label, self.server_microphone_codecs_label)
        self.client_packet_encoders_label = label()
        self.server_packet_encoders_label = label()
        tb.new_row("Packet Encoders", self.client_packet_encoders_label, self.server_packet_encoders_label)
        self.client_packet_compressors_label = label()
        self.server_packet_compressors_label = label()
        tb.new_row("Packet Compressors", self.client_packet_compressors_label, self.server_packet_compressors_label)

        # Connection Table:
        tb, _ = self.table_tab("connect.png", "Connection", self.populate_connection)
        tb.new_row("Server Endpoint", label(self.connection.target))
        if self.client.server_display:
            tb.new_row("Server Display", label(prettify_plug_name(self.client.server_display)))
        hostname = scaps.strget("hostname")
        if hostname:
            tb.new_row("Server Hostname", label(hostname))
        if self.client.server_platform:
            tb.new_row("Server Platform", label(self.client.server_platform))
        self.server_load_label = label()
        tb.new_row("Server Load", self.server_load_label, label_tooltip="Average over 1, 5 and 15 minutes")
        self.session_started_label = label()
        tb.new_row("Session Started", self.session_started_label)
        self.session_connected_label = label()
        tb.new_row("Session Connected", self.session_connected_label)
        self.input_packets_label = label()
        tb.new_row("Packets Received", self.input_packets_label)
        self.input_bytes_label = label()
        tb.new_row("Bytes Received", self.input_bytes_label)
        self.output_packets_label = label()
        tb.new_row("Packets Sent", self.output_packets_label)
        self.output_bytes_label = label()
        tb.new_row("Bytes Sent", self.output_bytes_label)
        self.compression_label = label()
        tb.new_row("Encoding + Compression", self.compression_label)
        self.connection_type_label = label()
        tb.new_row("Connection Type", self.connection_type_label)
        self.input_encryption_label = label()
        tb.new_row("Input Encryption", self.input_encryption_label)
        self.output_encryption_label = label()
        tb.new_row("Output Encryption", self.output_encryption_label)

        self.speaker_label = label()
        self.speaker_details = label(font="monospace 10")
        tb.new_row("Speaker", self.speaker_label, self.speaker_details)
        self.microphone_label = label()
        tb.new_row("Microphone", self.microphone_label)

        # Details:
        tb, stats_box = self.table_tab("browse.png", "Statistics", self.populate_statistics)
        tb.widget_xalign = 1.0
        tb.attach(title_box(""), 0, xoptions=EXPAND|FILL, xpadding=0)
        tb.attach(title_box("Latest"), 1, xoptions=EXPAND|FILL, xpadding=0)
        tb.attach(title_box("Minimum"), 2, xoptions=EXPAND|FILL, xpadding=0)
        tb.attach(title_box("Average"), 3, xoptions=EXPAND|FILL, xpadding=0)
        tb.attach(title_box("90 percentile"), 4, xoptions=EXPAND|FILL, xpadding=0)
        tb.attach(title_box("Maximum"), 5, xoptions=EXPAND|FILL, xpadding=0)
        tb.inc()

        def maths_labels():
            return label(), label(), label(), label(), label()
        self.server_latency_labels = maths_labels()
        tb.add_row(label("Server Latency (ms)", "The time it takes for the server to respond to pings"),
                   *self.server_latency_labels)
        self.client_latency_labels = maths_labels()
        tb.add_row(label("Client Latency (ms)", "The time it takes for the client to respond to pings, as measured by the server"),
                   *self.client_latency_labels)
        if self.client.windows_enabled:
            if self.client.server_info_request:
                self.batch_labels = maths_labels()
                tb.add_row(label("Batch Delay (ms)", "How long the server waits for new screen updates to accumulate before processing them"),
                           *self.batch_labels)
                self.damage_labels = maths_labels()
                tb.add_row(label("Damage Latency (ms)", "The time it takes to compress a frame and pass it to the OS network layer"),
                           *self.damage_labels)
                self.quality_labels = maths_labels()
                tb.add_row(label("Encoding Quality (pct)"), *self.quality_labels)
                self.speed_labels = maths_labels()
                tb.add_row(label("Encoding Speed (pct)"), *self.speed_labels)

            self.decoding_labels = maths_labels()
            tb.add_row(label("Decoding Latency (ms)", "How long it takes the client to decode a screen update"), *self.decoding_labels)
            self.regions_per_second_labels = maths_labels()
            tb.add_row(label("Regions/s", "The number of screen updates per second (includes both partial and full screen updates)"), *self.regions_per_second_labels)
            self.regions_sizes_labels = maths_labels()
            tb.add_row(label("Pixels/region", "The number of pixels per screen update"), *self.regions_sizes_labels)
            self.pixels_per_second_labels = maths_labels()
            tb.add_row(label("Pixels/s", "The number of pixels processed per second"), *self.pixels_per_second_labels)

            #Window count stats:
            wtb = TableBuilder()
            stats_box.add(wtb.get_table())
            #title row:
            wtb.attach(title_box(""), 0, xoptions=EXPAND|FILL, xpadding=0)
            wtb.attach(title_box("Regular"), 1, xoptions=EXPAND|FILL, xpadding=0)
            wtb.attach(title_box("Transient"), 2, xoptions=EXPAND|FILL, xpadding=0)
            wtb.attach(title_box("Trays"), 3, xoptions=EXPAND|FILL, xpadding=0)
            if self.client.client_supports_opengl:
                wtb.attach(title_box("OpenGL"), 4, xoptions=EXPAND|FILL, xpadding=0)
            wtb.inc()

            wtb.attach(label("Windows:"), 0, xoptions=EXPAND|FILL, xpadding=0)
            self.windows_managed_label = label()
            wtb.attach(self.windows_managed_label, 1)
            self.transient_managed_label = label()
            wtb.attach(self.transient_managed_label, 2)
            self.trays_managed_label = label()
            wtb.attach(self.trays_managed_label, 3)
            if self.client.client_supports_opengl:
                self.opengl_label = label()
                wtb.attach(self.opengl_label, 4)

            #add encoder info:
            etb = TableBuilder()
            stats_box.add(etb.get_table())
            self.encoder_info_box = gtk.HBox(spacing=4)
            etb.new_row("Window Encoders", self.encoder_info_box)

        if not is_gtk3():
            #needs porting to cairo...
            self.graph_box = gtk.VBox(False, 10)
            self.add_tab("statistics.png", "Graphs", self.populate_graphs, self.graph_box)
            bandwidth_label = "Bandwidth used"
            if SHOW_PIXEL_STATS:
                bandwidth_label += ",\nand number of pixels rendered"
            self.bandwidth_graph = self.add_graph_button(bandwidth_label, self.save_graphs)
            self.connect("realize", self.populate_graphs)
            self.latency_graph = self.add_graph_button(None, self.save_graphs)
        self.pixel_in_data = deque(maxlen=N_SAMPLES+4)
        self.net_in_bytecount = deque(maxlen=N_SAMPLES+4)
        self.net_out_bytecount = deque(maxlen=N_SAMPLES+4)
        self.sound_in_bytecount = deque(maxlen=N_SAMPLES+4)
        self.sound_out_bytecount = deque(maxlen=N_SAMPLES+4)

        self.set_border_width(15)
        self.add(self.tab_box)
        if not is_gtk3():
            self.set_geometry_hints(self.tab_box)
        def window_deleted(*args):
            self.is_closed = True
        self.connect('delete_event', window_deleted)
        self.show_tab(self.tabs[0][2])
        self.set_size_request(-1, 480)
        self.init_counters()
        self.populate()
        self.populate_all()
        gobject.timeout_add(1000, self.populate)
        gobject.timeout_add(100, self.populate_tab)
        add_close_accel(self, self.destroy)
示例#17
0
    def __init__(self, client, session_name, window_icon_pixbuf, conn, get_pixbuf):
        gtk.Window.__init__(self)
        self.client = client
        self.session_name = session_name
        self.connection = conn
        self.last_populate_time = 0
        self.last_populate_statistics = 0
        self.is_closed = False
        self.get_pixbuf = get_pixbuf
        if not self.session_name or self.session_name=="Xpra":
            title = "Session Info"
        else:
            title = "%s: Session Info" % self.session_name
        self.set_title(title)
        self.set_destroy_with_parent(True)
        self.set_resizable(True)
        self.set_decorated(True)
        if window_icon_pixbuf:
            self.set_icon(window_icon_pixbuf)
        self.set_position(WIN_POS_CENTER)

        #tables on the left in a vbox with buttons at the top:
        self.tab_box = gtk.VBox(False, 0)
        self.tab_button_box = gtk.HBox(True, 0)
        self.tabs = []          #pairs of button, table
        self.populate_cb = None
        self.tab_box.pack_start(self.tab_button_box, expand=False, fill=True, padding=0)

        #Package Table:
        tb, _ = self.table_tab("package.png", "Software", self.populate_package)
        #title row:
        tb.attach(title_box(""), 0, xoptions=EXPAND|FILL, xpadding=0)
        tb.attach(title_box("Client"), 1, xoptions=EXPAND|FILL, xpadding=0)
        tb.attach(title_box("Server"), 2, xoptions=EXPAND|FILL, xpadding=0)
        tb.inc()

        def make_os_str(*args):
            s = os_info(*args)
            return "\n".join(s)
        distro = ""
        if hasattr(python_platform, "linux_distribution"):
            distro = python_platform.linux_distribution()
        LOCAL_PLATFORM_NAME = make_os_str(sys.platform, python_platform.release(), python_platform.platform(), distro)
        SERVER_PLATFORM_NAME = make_os_str(self.client._remote_platform, self.client._remote_platform_release, self.client._remote_platform_platform, self.client._remote_platform_linux_distribution)
        tb.new_row("Operating System", label(LOCAL_PLATFORM_NAME), label(SERVER_PLATFORM_NAME))
        scaps = self.client.server_capabilities
        from xpra.__init__ import __version__
        tb.new_row("Xpra", label(__version__), label(self.client._remote_version or "unknown"))
        cl_rev, cl_ch, cl_date = "unknown", "", ""
        try:
            from xpra.build_info import BUILD_DATE as cl_date, BUILD_TIME as cl_time
            from xpra.src_info import REVISION as cl_rev, LOCAL_MODIFICATIONS as cl_ch      #@UnresolvedImport
        except:
            pass
        def make_version_str(version):
            if version and type(version) in (tuple, list):
                version = ".".join([str(x) for x in version])
            return version or "unknown"
        def server_info(*prop_names):
            for x in prop_names:
                v = scaps.capsget(x)
                if v is not None:
                    return v
                if self.client.server_last_info:
                    v = self.client.server_last_info.get(x)
                if v is not None:
                    return v
            return None
        def server_version_info(*prop_names):
            return make_version_str(server_info(*prop_names))
        def make_revision_str(rev, changes):
            if not changes:
                return rev
            return "%s (%s changes)" % (rev, changes)
        def make_datetime(date, time):
            if not time:
                return date
            return "%s %s" % (date, time)
        tb.new_row("Revision", label(make_revision_str(cl_rev, cl_ch)),
                               label(make_revision_str(self.client._remote_revision, server_version_info("build.local_modifications", "local_modifications"))))
        tb.new_row("Build date", label(make_datetime(cl_date, cl_time)),
                                 label(make_datetime(server_info("build_date", "build.date"), server_info("build.time"))))
        gtk_version_info = get_gtk_version_info()
        def client_vinfo(prop, fallback="unknown"):
            k = "%s.version" % prop
            return label(make_version_str(gtk_version_info.get(k, fallback)))
        tb.new_row("Glib",      client_vinfo("glib"),       label(server_version_info("glib.version")))
        tb.new_row("Gobject",   client_vinfo("gobject"),    label(server_version_info("gobject.version", "pygtk_version")))
        tb.new_row("PyGTK",     client_vinfo("pygtk", ""),  label(server_version_info("pygtk.version", "pygtk_version")))
        tb.new_row("GTK",       client_vinfo("gtk"),        label(server_version_info("gtk.version", "gtk_version")))
        tb.new_row("GDK",       client_vinfo("gdk"),        label(server_version_info("gdk.version", "gdk_version")))
        tb.new_row("Cairo",     client_vinfo("cairo"),      label(server_version_info("cairo.version", "cairo_version")))
        tb.new_row("Pango",     client_vinfo("pango"),      label(server_version_info("pango.version", "cairo_version")))
        tb.new_row("Python", label(python_platform.python_version()), label(server_version_info("server.python.version", "python_version", "python.version")))

        cl_gst_v, cl_pygst_v = "", ""
        try:
            from xpra.sound.gstreamer_util import gst_version as cl_gst_v, pygst_version as cl_pygst_v
        except Exception, e:
            log("cannot load gstreamer: %s", e)
示例#18
0
 def label(self, text):
     return label(text, font="sans 14")
示例#19
0
    def __init__(self, client, session_name, window_icon_pixbuf, conn,
                 get_pixbuf):
        gtk.Window.__init__(self)
        self.client = client
        self.session_name = session_name
        self.connection = conn
        self.last_populate_time = 0
        self.last_populate_statistics = 0
        self.is_closed = False
        self.get_pixbuf = get_pixbuf
        if self.session_name == "Xpra":
            title = "Session Info"
        else:
            title = "%s: Session Info" % self.session_name
        self.set_title(title)
        self.set_destroy_with_parent(True)
        self.set_resizable(True)
        self.set_decorated(True)
        if window_icon_pixbuf:
            self.set_icon(window_icon_pixbuf)
        if is_gtk3():
            self.set_position(gtk.WindowPosition.CENTER)
        else:
            self.set_position(gtk.WIN_POS_CENTER)

        #tables on the left in a vbox with buttons at the top:
        self.tab_box = gtk.VBox(False, 0)
        self.tab_button_box = gtk.HBox(True, 0)
        self.tabs = []  #pairs of button, table
        self.populate_cb = None
        self.tab_box.pack_start(self.tab_button_box,
                                expand=False,
                                fill=True,
                                padding=0)

        #Package Table:
        tb = self.table_tab("package.png", "Software", self.populate_package)
        #title row:
        tb.attach(title_box(""), 0, xoptions=gtk.EXPAND | gtk.FILL, xpadding=0)
        tb.attach(title_box("Client"),
                  1,
                  xoptions=gtk.EXPAND | gtk.FILL,
                  xpadding=0)
        tb.attach(title_box("Server"),
                  2,
                  xoptions=gtk.EXPAND | gtk.FILL,
                  xpadding=0)
        tb.inc()

        def make_os_str(sys_platform, platform_release, platform_platform,
                        platform_linux_distribution):
            s = platform_name(sys_platform, platform_release)
            if platform_linux_distribution and len(
                    platform_linux_distribution) == 3 and len(
                        platform_linux_distribution[0]) > 0:
                s += "\n%s" % (" ".join(platform_linux_distribution))
            elif platform_platform:
                s += "\n%s" % platform_platform
            return s

        LOCAL_PLATFORM_NAME = make_os_str(sys.platform,
                                          python_platform.release(),
                                          python_platform.platform(),
                                          python_platform.linux_distribution())
        SERVER_PLATFORM_NAME = make_os_str(
            self.client._remote_platform, self.client._remote_platform_release,
            self.client._remote_platform_platform,
            self.client._remote_platform_linux_distribution)
        tb.new_row("Operating System", label(LOCAL_PLATFORM_NAME),
                   label(SERVER_PLATFORM_NAME))
        scaps = self.client.server_capabilities
        from xpra.__init__ import __version__
        tb.new_row("Xpra", label(__version__),
                   label(self.client._remote_version or "unknown"))
        cl_rev, cl_ch, cl_date = "unknown", "", ""
        try:
            from xpra.build_info import BUILD_DATE as cl_date
            from xpra.src_info import REVISION as cl_rev, LOCAL_MODIFICATIONS as cl_ch
        except:
            pass

        def make_version_str(version):
            if version and type(version) in (tuple, list):
                version = ".".join([str(x) for x in version])
            return version or "unknown"

        def server_info(*prop_names):
            for x in prop_names:
                v = scaps.get(x)
                if v is not None:
                    return v
            return None

        def server_version_info(*prop_names):
            return make_version_str(server_info(*prop_names))

        tb.new_row("Revision", label(cl_rev),
                   label(make_version_str(self.client._remote_revision)))
        tb.new_row(
            "Local Changes", label(cl_ch),
            label(
                server_version_info("build.local_modifications",
                                    "local_modifications")))
        tb.new_row("Build date", label(cl_date),
                   label(server_info("build_date", "build.date")))

        def client_version_info(prop_name):
            info = "unknown"
            if hasattr(gtk, prop_name):
                info = make_version_str(getattr(gtk, prop_name))
            return info

        if is_gtk3():
            tb.new_row("PyGobject", label(gobject._version))
            tb.new_row("Client GDK", label(gdk._version))
            tb.new_row("GTK", label(gtk._version),
                       label(server_version_info("gtk_version")))
        else:
            tb.new_row(
                "PyGTK", label(client_version_info("pygtk_version")),
                label(server_version_info("pygtk.version", "pygtk_version")))
            tb.new_row(
                "GTK", label(client_version_info("gtk_version")),
                label(server_version_info("gtk.version", "gtk_version")))
        tb.new_row(
            "Python", label(python_platform.python_version()),
            label(
                server_version_info("server.python.version",
                                    "python_version")))
        cl_gst_v, cl_pygst_v = "", ""
        if HAS_SOUND:
            try:
                from xpra.sound.gstreamer_util import gst_version as cl_gst_v, pygst_version as cl_pygst_v
            except:
                pass
        tb.new_row(
            "GStreamer", label(make_version_str(cl_gst_v)),
            label(server_version_info("sound.gst.version", "gst_version")))
        tb.new_row(
            "pygst", label(make_version_str(cl_pygst_v)),
            label(server_version_info("sound.pygst.version", "pygst_version")))
        tb.new_row(
            "OpenGL",
            label(
                make_version_str(self.client.opengl_props.get("opengl",
                                                              "n/a"))),
            label("n/a"))
        tb.new_row(
            "OpenGL Vendor",
            label(make_version_str(self.client.opengl_props.get("vendor",
                                                                ""))),
            label("n/a"))
        tb.new_row(
            "PyOpenGL",
            label(
                make_version_str(
                    self.client.opengl_props.get("pyopengl", "n/a"))),
            label("n/a"))

        # Features Table:
        tb = self.table_tab("features.png", "Features", self.populate_features)
        randr_box = gtk.HBox(False, 20)
        self.server_randr_label = label()
        self.server_randr_icon = gtk.Image()
        randr_box.add(self.server_randr_icon)
        randr_box.add(self.server_randr_label)
        tb.new_row("RandR Support", randr_box)
        opengl_box = gtk.HBox(False, 20)
        self.client_opengl_label = label()
        self.client_opengl_label.set_line_wrap(True)
        self.client_opengl_icon = gtk.Image()
        opengl_box.add(self.client_opengl_icon)
        opengl_box.add(self.client_opengl_label)
        tb.new_row("Client OpenGL", opengl_box)
        self.opengl_buffering = label()
        tb.new_row("OpenGL Buffering", self.opengl_buffering)
        self.server_encodings_label = label()
        tb.new_row("Server Encodings", self.server_encodings_label)
        self.client_encodings_label = label()
        tb.new_row("Client Encodings", self.client_encodings_label)
        self.server_mmap_icon = gtk.Image()
        tb.new_row("Memory Mapped Transfers", self.server_mmap_icon)
        self.server_clipboard_icon = gtk.Image()
        tb.new_row("Clipboard", self.server_clipboard_icon)
        self.server_notifications_icon = gtk.Image()
        tb.new_row("Notification Forwarding", self.server_notifications_icon)
        self.server_bell_icon = gtk.Image()
        tb.new_row("Bell Forwarding", self.server_bell_icon)
        self.server_cursors_icon = gtk.Image()
        tb.new_row("Cursor Forwarding", self.server_cursors_icon)
        speaker_box = gtk.HBox(False, 20)
        self.server_speaker_icon = gtk.Image()
        speaker_box.add(self.server_speaker_icon)
        self.speaker_codec_label = label()
        speaker_box.add(self.speaker_codec_label)
        tb.new_row("Speaker Forwarding", speaker_box)
        self.server_speaker_codecs_label = label()
        tb.new_row("Server Codecs", self.server_speaker_codecs_label)
        self.client_speaker_codecs_label = label()
        tb.new_row("Client Codecs", self.client_speaker_codecs_label)
        microphone_box = gtk.HBox(False, 20)
        self.server_microphone_icon = gtk.Image()
        microphone_box.add(self.server_microphone_icon)
        self.microphone_codec_label = label()
        microphone_box.add(self.microphone_codec_label)
        tb.new_row("Microphone Forwarding", microphone_box)
        self.server_microphone_codecs_label = label()
        tb.new_row("Server Codecs", self.server_microphone_codecs_label)
        self.client_microphone_codecs_label = label()
        tb.new_row("Client Codecs", self.client_microphone_codecs_label)

        # Connection Table:
        tb = self.table_tab("connect.png", "Connection",
                            self.populate_connection)
        tb.new_row("Server Endpoint", label(self.connection.target))
        if self.client.server_display:
            tb.new_row("Server Display", label(self.client.server_display))
        if "hostname" in scaps:
            tb.new_row("Server Hostname", label(scaps.get("hostname")))
        if self.client.server_platform:
            tb.new_row("Server Platform", label(self.client.server_platform))
        self.server_load_label = label()
        tb.new_row("Server Load",
                   self.server_load_label,
                   label_tooltip="Average over 1, 5 and 15 minutes")
        self.session_started_label = label()
        tb.new_row("Session Started", self.session_started_label)
        self.session_connected_label = label()
        tb.new_row("Session Connected", self.session_connected_label)
        self.input_packets_label = label()
        tb.new_row("Packets Received", self.input_packets_label)
        self.input_bytes_label = label()
        tb.new_row("Bytes Received", self.input_bytes_label)
        self.output_packets_label = label()
        tb.new_row("Packets Sent", self.output_packets_label)
        self.output_bytes_label = label()
        tb.new_row("Bytes Sent", self.output_bytes_label)
        self.compression_label = label()
        tb.new_row("Compression Level", self.compression_label)
        self.connection_type_label = label()
        tb.new_row("Connection Type", self.connection_type_label)
        self.input_encryption_label = label()
        tb.new_row("Input Encryption", self.input_encryption_label)
        self.output_encryption_label = label()
        tb.new_row("Output Encryption", self.output_encryption_label)

        self.speaker_label = label()
        self.speaker_details = label(font="monospace 10")
        tb.new_row("Speaker", self.speaker_label, self.speaker_details)
        self.microphone_label = label()
        tb.new_row("Microphone", self.microphone_label)

        # Details:
        tb = self.table_tab("browse.png", "Statistics",
                            self.populate_statistics)
        tb.widget_xalign = 1.0
        tb.attach(title_box(""), 0, xoptions=gtk.EXPAND | gtk.FILL, xpadding=0)
        tb.attach(title_box("Latest"),
                  1,
                  xoptions=gtk.EXPAND | gtk.FILL,
                  xpadding=0)
        tb.attach(title_box("Minimum"),
                  2,
                  xoptions=gtk.EXPAND | gtk.FILL,
                  xpadding=0)
        tb.attach(title_box("Average"),
                  3,
                  xoptions=gtk.EXPAND | gtk.FILL,
                  xpadding=0)
        tb.attach(title_box("90 percentile"),
                  4,
                  xoptions=gtk.EXPAND | gtk.FILL,
                  xpadding=0)
        tb.attach(title_box("Maximum"),
                  5,
                  xoptions=gtk.EXPAND | gtk.FILL,
                  xpadding=0)
        tb.inc()

        def maths_labels():
            return label(), label(), label(), label(), label()

        self.server_latency_labels = maths_labels()
        tb.add_row(label("Server Latency (ms)"), *self.server_latency_labels)
        self.client_latency_labels = maths_labels()
        tb.add_row(label("Client Latency (ms)"), *self.client_latency_labels)
        if self.client.windows_enabled:
            if self.client.server_info_request:
                self.batch_labels = maths_labels()
                tb.add_row(label("Batch Delay (ms)"), *self.batch_labels)
                self.damage_labels = maths_labels()
                tb.add_row(label("Damage Latency (ms)"), *self.damage_labels)
                self.quality_labels = maths_labels()
                tb.add_row(label("Encoding Quality (pct)"),
                           *self.quality_labels)
                self.speed_labels = maths_labels()
                tb.add_row(label("Encoding Speed (pct)"), *self.speed_labels)

            self.decoding_labels = maths_labels()
            tb.add_row(label("Decoding Latency (ms)"), *self.decoding_labels)
            self.regions_per_second_labels = maths_labels()
            tb.add_row(label("Regions/s"), *self.regions_per_second_labels)
            self.regions_sizes_labels = maths_labels()
            tb.add_row(label("Pixels/region"), *self.regions_sizes_labels)
            self.pixels_per_second_labels = maths_labels()
            tb.add_row(label("Pixels/s"), *self.pixels_per_second_labels)

            self.windows_managed_label = label()
            tb.new_row("Regular Windows", self.windows_managed_label),
            self.transient_managed_label = label()
            tb.new_row("Transient Windows", self.transient_managed_label),
            self.trays_managed_label = label()
            tb.new_row("Trays Managed", self.trays_managed_label),
            if self.client.client_supports_opengl:
                self.opengl_label = label()
                tb.new_row("OpenGL Windows", self.opengl_label),

        self.graph_box = gtk.VBox(False, 10)
        self.add_tab("statistics.png", "Graphs", self.populate_graphs,
                     self.graph_box)
        bandwidth_label = "Number of bytes measured by the networks sockets"
        if SHOW_PIXEL_STATS:
            bandwidth_label += ",\nand number of pixels rendered"
        self.bandwidth_graph = self.add_graph_button(bandwidth_label,
                                                     self.save_graphs)
        self.latency_graph = self.add_graph_button(
            "The time it takes to send an echo packet and get the reply",
            self.save_graphs)
        self.pixel_in_data = maxdeque(N_SAMPLES + 4)
        self.net_in_bytecount = maxdeque(N_SAMPLES + 4)
        self.net_out_bytecount = maxdeque(N_SAMPLES + 4)

        self.set_border_width(15)
        self.add(self.tab_box)
        if not is_gtk3():
            self.set_geometry_hints(self.tab_box)

        def window_deleted(*args):
            self.is_closed = True

        self.connect('delete_event', window_deleted)
        self.show_tab(self.tabs[0][1])
        self.set_size_request(-1, 480)
        self.populate()
        self.populate_all()
        gobject.timeout_add(1000, self.populate)
        gobject.timeout_add(100, self.populate_tab)
        self.connect("realize", self.populate_graphs)
        add_close_accel(self, self.destroy)