Merge
This commit is contained in:
commit
0c47294dbd
1
.gitignore
vendored
1
.gitignore
vendored
@ -25,7 +25,6 @@ missing
|
|||||||
py-compile
|
py-compile
|
||||||
stamp-h1
|
stamp-h1
|
||||||
dbus-installed.conf
|
dbus-installed.conf
|
||||||
dbus-installed-094.conf
|
|
||||||
intltool-extract
|
intltool-extract
|
||||||
intltool-extract.in
|
intltool-extract.in
|
||||||
intltool-merge
|
intltool-merge
|
||||||
|
@ -3,7 +3,7 @@ SUBDIRS = activities lib po shell sugar services tools
|
|||||||
ACLOCAL_AMFLAGS = -I m4
|
ACLOCAL_AMFLAGS = -I m4
|
||||||
|
|
||||||
dbusconfdir = $(pkgdatadir)
|
dbusconfdir = $(pkgdatadir)
|
||||||
dbusconf_DATA = dbus-installed.conf dbus-installed-094.conf
|
dbusconf_DATA = dbus-installed.conf
|
||||||
|
|
||||||
bin_SCRIPTS = \
|
bin_SCRIPTS = \
|
||||||
sugar-emulator \
|
sugar-emulator \
|
||||||
|
@ -51,7 +51,6 @@ AM_GLIB_GNU_GETTEXT
|
|||||||
AC_OUTPUT([
|
AC_OUTPUT([
|
||||||
Makefile
|
Makefile
|
||||||
dbus-installed.conf
|
dbus-installed.conf
|
||||||
dbus-installed-094.conf
|
|
||||||
activities/Makefile
|
activities/Makefile
|
||||||
activities/web/Makefile
|
activities/web/Makefile
|
||||||
activities/chat/Makefile
|
activities/chat/Makefile
|
||||||
@ -72,6 +71,13 @@ shell/view/Makefile
|
|||||||
shell/view/home/Makefile
|
shell/view/home/Makefile
|
||||||
shell/view/frame/Makefile
|
shell/view/frame/Makefile
|
||||||
shell/model/Makefile
|
shell/model/Makefile
|
||||||
|
shell/console/Makefile
|
||||||
|
shell/console/plugins/Makefile
|
||||||
|
shell/console/plugins/clean_size/Makefile
|
||||||
|
shell/console/plugins/cpu/Makefile
|
||||||
|
shell/console/plugins/dirty_size/Makefile
|
||||||
|
shell/console/plugins/memphis_init/Makefile
|
||||||
|
shell/console/procmem/Makefile
|
||||||
sugar/Makefile
|
sugar/Makefile
|
||||||
sugar/__installed__.py
|
sugar/__installed__.py
|
||||||
sugar/activity/Makefile
|
sugar/activity/Makefile
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
<!-- This configuration file controls the per-user-login-session message bus.
|
|
||||||
Add a session-local.conf and edit that rather than changing this
|
|
||||||
file directly. -->
|
|
||||||
|
|
||||||
<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
|
|
||||||
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
|
|
||||||
<busconfig>
|
|
||||||
<!-- Our well-known bus type, don't change this -->
|
|
||||||
<type>session</type>
|
|
||||||
|
|
||||||
<listen>unix:tmpdir=/tmp</listen>
|
|
||||||
|
|
||||||
<servicedir>@prefix@/share/sugar/activities</servicedir>
|
|
||||||
<servicedir>@prefix@/share/sugar/services</servicedir>
|
|
||||||
<servicedir>/tmp/sugar-services</servicedir>
|
|
||||||
|
|
||||||
<policy context="default">
|
|
||||||
<!-- Allow everything to be sent -->
|
|
||||||
<allow send_destination="*"/>
|
|
||||||
<!-- Allow everything to be received -->
|
|
||||||
<allow eavesdrop="true"/>
|
|
||||||
<!-- Allow anyone to own anything -->
|
|
||||||
<allow own="*"/>
|
|
||||||
</policy>
|
|
||||||
|
|
||||||
</busconfig>
|
|
@ -1,25 +0,0 @@
|
|||||||
<!-- This configuration file controls the per-user-login-session message bus.
|
|
||||||
Add a session-local.conf and edit that rather than changing this
|
|
||||||
file directly. -->
|
|
||||||
|
|
||||||
<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
|
|
||||||
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
|
|
||||||
<busconfig>
|
|
||||||
<!-- Our well-known bus type, don't change this -->
|
|
||||||
<type>session</type>
|
|
||||||
|
|
||||||
<listen>unix:tmpdir=/tmp</listen>
|
|
||||||
|
|
||||||
<servicedir>/tmp/sugar</servicedir>
|
|
||||||
<servicedir>/tmp/sugar-services</servicedir>
|
|
||||||
|
|
||||||
<policy context="default">
|
|
||||||
<!-- Allow everything to be sent -->
|
|
||||||
<allow send_destination="*"/>
|
|
||||||
<!-- Allow everything to be received -->
|
|
||||||
<allow eavesdrop="true"/>
|
|
||||||
<!-- Allow anyone to own anything -->
|
|
||||||
<allow own="*"/>
|
|
||||||
</policy>
|
|
||||||
|
|
||||||
</busconfig>
|
|
@ -1,11 +1,11 @@
|
|||||||
SUBDIRS = conf data model view
|
SUBDIRS = conf data model view console
|
||||||
|
|
||||||
bin_SCRIPTS = \
|
bin_SCRIPTS = \
|
||||||
sugar-activity \
|
sugar-activity \
|
||||||
sugar-activity-factory \
|
sugar-activity-factory \
|
||||||
sugar-log-viewer \
|
|
||||||
sugar-shell \
|
sugar-shell \
|
||||||
sugar-shutdown
|
sugar-shutdown \
|
||||||
|
sugar-devel-console
|
||||||
|
|
||||||
sugardir = $(pkgdatadir)/shell
|
sugardir = $(pkgdatadir)/shell
|
||||||
sugar_PYTHON = \
|
sugar_PYTHON = \
|
||||||
|
10
shell/console/Makefile.am
Normal file
10
shell/console/Makefile.am
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
SUBDIRS = plugins procmem
|
||||||
|
|
||||||
|
sugardir = $(pkgdatadir)/shell/console
|
||||||
|
sugar_PYTHON = \
|
||||||
|
__init__.py \
|
||||||
|
console.py \
|
||||||
|
memphis.py \
|
||||||
|
logviewer.py \
|
||||||
|
terminal.py \
|
||||||
|
plugin.py
|
1
shell/console/__init__.py
Normal file
1
shell/console/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
|
43
shell/console/console.py
Executable file
43
shell/console/console.py
Executable file
@ -0,0 +1,43 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import gtk
|
||||||
|
|
||||||
|
# Console interfaces
|
||||||
|
import memphis
|
||||||
|
import logviewer
|
||||||
|
import terminal
|
||||||
|
|
||||||
|
window = gtk.Window()
|
||||||
|
window.set_title('Developer console')
|
||||||
|
|
||||||
|
width = gtk.gdk.screen_width() * 95 / 100
|
||||||
|
height = gtk.gdk.screen_height() * 95 / 100
|
||||||
|
|
||||||
|
window.set_default_size(width, height)
|
||||||
|
|
||||||
|
window.realize()
|
||||||
|
window.window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG)
|
||||||
|
|
||||||
|
# Memphis interface
|
||||||
|
memphis_widget = memphis.Interface().widget
|
||||||
|
memphis_widget.show()
|
||||||
|
|
||||||
|
# Log viewer interface
|
||||||
|
logviewer_widget = logviewer.Interface().widget
|
||||||
|
logviewer_widget.show()
|
||||||
|
|
||||||
|
# Terminal interface
|
||||||
|
terminal_widget = terminal.Interface().widget
|
||||||
|
terminal_widget.show()
|
||||||
|
|
||||||
|
# Notebook
|
||||||
|
notebook = gtk.Notebook()
|
||||||
|
notebook.append_page(memphis_widget, gtk.Label('Memphis'))
|
||||||
|
notebook.append_page(logviewer_widget, gtk.Label('Log Viewer'))
|
||||||
|
notebook.append_page(terminal_widget, gtk.Label('Terminal'))
|
||||||
|
|
||||||
|
notebook.show()
|
||||||
|
|
||||||
|
window.add(notebook)
|
||||||
|
window.show()
|
||||||
|
gtk.main()
|
13
shell/sugar-log-viewer → shell/console/logviewer.py
Executable file → Normal file
13
shell/sugar-log-viewer → shell/console/logviewer.py
Executable file → Normal file
@ -91,18 +91,11 @@ class MultiLogView(gtk.Notebook):
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
window = gtk.Window()
|
class Interface:
|
||||||
window.set_default_size(gtk.gdk.screen_width() * 3 / 4,
|
|
||||||
gtk.gdk.screen_height() * 3 / 4)
|
|
||||||
|
|
||||||
window.realize()
|
|
||||||
window.window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG)
|
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
path = os.path.join(env.get_profile_path(), 'logs')
|
path = os.path.join(env.get_profile_path(), 'logs')
|
||||||
viewer = MultiLogView(path)
|
viewer = MultiLogView(path)
|
||||||
window.add(viewer)
|
|
||||||
viewer.show()
|
viewer.show()
|
||||||
|
self.widget = viewer
|
||||||
|
|
||||||
window.show()
|
|
||||||
|
|
||||||
gtk.main()
|
|
182
shell/console/memphis.py
Normal file
182
shell/console/memphis.py
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import sys, os
|
||||||
|
import string
|
||||||
|
import wnck
|
||||||
|
import plugin
|
||||||
|
|
||||||
|
from procmem import proc
|
||||||
|
|
||||||
|
try:
|
||||||
|
import gtk
|
||||||
|
import gtk.gdk
|
||||||
|
import gobject
|
||||||
|
except:
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
class Interface:
|
||||||
|
|
||||||
|
store_data_types = []
|
||||||
|
store_data_types_details = []
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
|
||||||
|
# Our GtkTree (Treeview)
|
||||||
|
self.treeview = gtk.TreeView()
|
||||||
|
self.widget = self.treeview
|
||||||
|
|
||||||
|
# Loading plugins
|
||||||
|
self.plg = plugin.Plugin()
|
||||||
|
|
||||||
|
# TOP data types (columns)
|
||||||
|
self.store_data_types = []
|
||||||
|
|
||||||
|
for plg in self.plg.list:
|
||||||
|
plg_data = plg.INTERNALS
|
||||||
|
|
||||||
|
# Give plugin object to plugin
|
||||||
|
plg.INTERNALS['Plg'] = self.plg
|
||||||
|
|
||||||
|
# Creating a store model and loading process data to Treeview
|
||||||
|
# self.store_data_types, ex [int, str, str, str, int,...]
|
||||||
|
#self.store = gtk.TreeStore(*self.store_data_types)
|
||||||
|
self.data = Data(self.treeview, self.plg.list)
|
||||||
|
|
||||||
|
class Data:
|
||||||
|
|
||||||
|
treeview = None
|
||||||
|
last_col_index = 0
|
||||||
|
|
||||||
|
store_data_cols = []
|
||||||
|
store_data_types = []
|
||||||
|
store_data_types_details = []
|
||||||
|
|
||||||
|
def __init__(self, treeview, plg_list):
|
||||||
|
|
||||||
|
# Top data types
|
||||||
|
self.plg_list = plg_list
|
||||||
|
|
||||||
|
for plg in self.plg_list:
|
||||||
|
|
||||||
|
if plg.INTERNALS['top_data'] != None:
|
||||||
|
last_dt = len(self.store_data_types)
|
||||||
|
|
||||||
|
if last_dt > 0:
|
||||||
|
last_dt -= 1
|
||||||
|
|
||||||
|
len_dt = len(plg.INTERNALS['top_data'])
|
||||||
|
|
||||||
|
self.store_data_types_details.append({"plugin": plg, "init": last_dt, "end": last_dt + len_dt})
|
||||||
|
|
||||||
|
for dt in plg.INTERNALS['top_data']:
|
||||||
|
self.store_data_types.append(dt)
|
||||||
|
|
||||||
|
for col in plg.INTERNALS['top_cols']:
|
||||||
|
self.store_data_cols.append(col)
|
||||||
|
|
||||||
|
# Set global treeview
|
||||||
|
self.treeview = treeview
|
||||||
|
|
||||||
|
# Basic columns
|
||||||
|
index = 0
|
||||||
|
for column_name in self.store_data_cols:
|
||||||
|
self.add_column(column_name, index)
|
||||||
|
index += 1
|
||||||
|
|
||||||
|
self.store = gtk.TreeStore(*self.store_data_types)
|
||||||
|
treeview.set_model(self.store)
|
||||||
|
|
||||||
|
# Update information every 1 second
|
||||||
|
gobject.timeout_add(500, self.load_data, treeview)
|
||||||
|
|
||||||
|
# Add a new column to the main treeview
|
||||||
|
def add_column(self, column_name, index):
|
||||||
|
cell = gtk.CellRendererText()
|
||||||
|
col_tv = gtk.TreeViewColumn(column_name, cell, text=index)
|
||||||
|
col_tv.set_resizable(True)
|
||||||
|
col_tv.connect('clicked', self.sort_column_clicked)
|
||||||
|
col_tv.set_property('clickable', True)
|
||||||
|
|
||||||
|
self.treeview.append_column(col_tv)
|
||||||
|
|
||||||
|
# Set the last column index added
|
||||||
|
self.last_col_index = index
|
||||||
|
|
||||||
|
# Sorting
|
||||||
|
def sort_column_clicked(self, TreeViewColumn):
|
||||||
|
cols = self.treeview.get_columns()
|
||||||
|
|
||||||
|
# Searching column index
|
||||||
|
index = 0
|
||||||
|
for col in cols:
|
||||||
|
if col == TreeViewColumn:
|
||||||
|
break
|
||||||
|
|
||||||
|
index += 1
|
||||||
|
|
||||||
|
self.store.set_sort_column_id(index, gtk.SORT_DESCENDING)
|
||||||
|
|
||||||
|
def load_data(self, treeview):
|
||||||
|
self.store.clear()
|
||||||
|
|
||||||
|
# Getting procfs data
|
||||||
|
self.procdata = proc.ProcInfo()
|
||||||
|
self.process_list = []
|
||||||
|
|
||||||
|
pids = []
|
||||||
|
screen = wnck.screen_get_default()
|
||||||
|
windows = screen.get_windows()
|
||||||
|
|
||||||
|
current_pid = os.getpid()
|
||||||
|
|
||||||
|
for win in windows:
|
||||||
|
pid = int(win.get_pid())
|
||||||
|
if current_pid != pid:
|
||||||
|
pids.append(pid)
|
||||||
|
|
||||||
|
self.process_list = set(pids)
|
||||||
|
|
||||||
|
# Sort rows using pid
|
||||||
|
#self.process_list.sort(key=operator.itemgetter('pid'))
|
||||||
|
self.process_iter = []
|
||||||
|
|
||||||
|
for pid in self.process_list:
|
||||||
|
pi = self.build_row(self.store, None, self.procdata, pid)
|
||||||
|
self.process_iter.append(pi)
|
||||||
|
|
||||||
|
treeview.set_rules_hint(True)
|
||||||
|
treeview.expand_all()
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def build_row(self, store, parent_iter, proc_data, pid):
|
||||||
|
data = []
|
||||||
|
|
||||||
|
pinfo = proc_data.MemoryInfo(pid)
|
||||||
|
|
||||||
|
# Look for plugins that need to update the top data treeview
|
||||||
|
for plg in self.plg_list:
|
||||||
|
plg_data = []
|
||||||
|
|
||||||
|
if plg.INTERNALS['top_data'] != None:
|
||||||
|
# data = [xxx, yyy,zzz,...]
|
||||||
|
plg_data = plg.info.plg_on_top_data_refresh(plg, pinfo)
|
||||||
|
|
||||||
|
for field in plg_data:
|
||||||
|
data.append(field)
|
||||||
|
|
||||||
|
pi = self.insert_row(store, parent_iter, data)
|
||||||
|
|
||||||
|
return pi
|
||||||
|
|
||||||
|
# Insert a Row in our TreeView
|
||||||
|
def insert_row(self, store, parent, row_data):
|
||||||
|
iter = store.insert_after(parent, None)
|
||||||
|
|
||||||
|
index = 0
|
||||||
|
|
||||||
|
for data in row_data:
|
||||||
|
store.set_value(iter, index , data)
|
||||||
|
index += 1
|
||||||
|
|
||||||
|
return iter
|
50
shell/console/plugin.py
Executable file
50
shell/console/plugin.py
Executable file
@ -0,0 +1,50 @@
|
|||||||
|
###############################################
|
||||||
|
# Memphis Plugin Support
|
||||||
|
###############################################
|
||||||
|
|
||||||
|
import sys, os, time
|
||||||
|
import gtk, gobject
|
||||||
|
|
||||||
|
from procmem import proc, proc_smaps, analysis
|
||||||
|
|
||||||
|
class Plugin:
|
||||||
|
|
||||||
|
# Plugin list
|
||||||
|
list = []
|
||||||
|
proc = proc.ProcInfo()
|
||||||
|
|
||||||
|
internal_plugin = "memphis_init"
|
||||||
|
plg_path = os.path.dirname(os.path.abspath(__file__)) + "/plugins"
|
||||||
|
|
||||||
|
# Frequency timer, managed by main program
|
||||||
|
freq_timer = 0
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
|
||||||
|
sys.path.insert(0, self.plg_path)
|
||||||
|
|
||||||
|
# Including memphis plugin
|
||||||
|
self.list.append(__import__(self.internal_plugin))
|
||||||
|
|
||||||
|
if os.path.isdir(self.plg_path):
|
||||||
|
# around dir entries
|
||||||
|
for plg in os.listdir(self.plg_path):
|
||||||
|
|
||||||
|
if plg == self.internal_plugin:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if os.path.isdir(self.plg_path + "/" + plg):
|
||||||
|
p = __import__(plg)
|
||||||
|
self.list.append(__import__(plg))
|
||||||
|
|
||||||
|
# Parse /proc/PID/smaps information
|
||||||
|
def proc_get_smaps(self, pid):
|
||||||
|
return proc_smaps.ProcSmaps(pid)
|
||||||
|
|
||||||
|
# Parse /proc/PID/maps information
|
||||||
|
def proc_get_maps(self, pid):
|
||||||
|
return proc_smaps.ProcMaps(pid)
|
||||||
|
|
||||||
|
def proc_analysis(self, pid):
|
||||||
|
return analysis.Analysis(pid)
|
||||||
|
|
4
shell/console/plugins/Makefile.am
Normal file
4
shell/console/plugins/Makefile.am
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
SUBDIRS = clean_size cpu dirty_size memphis_init
|
||||||
|
|
||||||
|
sugardir = $(pkgdatadir)/shell/console/plugins
|
||||||
|
sugar_PYTHON =
|
6
shell/console/plugins/clean_size/Makefile.am
Normal file
6
shell/console/plugins/clean_size/Makefile.am
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
sugardir = $(pkgdatadir)/shell/console/plugins/clean_size
|
||||||
|
sugar_PYTHON = \
|
||||||
|
README \
|
||||||
|
__init__.py \
|
||||||
|
info.py
|
2
shell/console/plugins/clean_size/README
Normal file
2
shell/console/plugins/clean_size/README
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
This plugin give support to get the clean size memory usage
|
||||||
|
by process using the /proc/PID/maps file.
|
16
shell/console/plugins/clean_size/__init__.py
Normal file
16
shell/console/plugins/clean_size/__init__.py
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
|
||||||
|
import info
|
||||||
|
|
||||||
|
INTERNALS = {
|
||||||
|
# Basic information
|
||||||
|
'PLGNAME': "Clean Size",
|
||||||
|
'TABNAME': None,
|
||||||
|
'AUTHOR': "Eduardo Silva",
|
||||||
|
'DESC': "Print the approx real memory usage",
|
||||||
|
|
||||||
|
# Plugin API
|
||||||
|
'Plg': None, # Plugin object
|
||||||
|
|
||||||
|
'top_data': [int], # Top data types needed by memphis core plugin
|
||||||
|
'top_cols': ["Approx Real Usage (kb)"]
|
||||||
|
}
|
15
shell/console/plugins/clean_size/info.py
Normal file
15
shell/console/plugins/clean_size/info.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
###########################################################
|
||||||
|
# Main function:
|
||||||
|
# -----------------
|
||||||
|
# self: self plugin object
|
||||||
|
# mself: memphis object / principal class
|
||||||
|
# pinfo: row with information about current tracing process
|
||||||
|
############################################################
|
||||||
|
|
||||||
|
def plg_on_top_data_refresh(self, pinfo):
|
||||||
|
|
||||||
|
# Get clean size
|
||||||
|
maps = self.INTERNALS['Plg'].proc_get_maps(pinfo['pid'])
|
||||||
|
|
||||||
|
size = (maps.clean_size/1024)
|
||||||
|
return [size]
|
6
shell/console/plugins/cpu/Makefile.am
Normal file
6
shell/console/plugins/cpu/Makefile.am
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
sugardir = $(pkgdatadir)/shell/console/plugins/cpu
|
||||||
|
sugar_PYTHON = \
|
||||||
|
README \
|
||||||
|
__init__.py \
|
||||||
|
info.py
|
2
shell/console/plugins/cpu/README
Normal file
2
shell/console/plugins/cpu/README
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
This plugin give support to draw the Virtual Memory Size
|
||||||
|
usage by the current tracing process.
|
23
shell/console/plugins/cpu/__init__.py
Normal file
23
shell/console/plugins/cpu/__init__.py
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import os
|
||||||
|
import info
|
||||||
|
|
||||||
|
INTERNALS = {
|
||||||
|
'PLGNAME': "cpu",
|
||||||
|
'TABNAME': None,
|
||||||
|
'AUTHOR': "Eduardo Silva",
|
||||||
|
'DESC': "Print CPU usage",
|
||||||
|
|
||||||
|
# Plugin API
|
||||||
|
'Plg': None, # Plugin object
|
||||||
|
'current_plg': None, # Current plugin object
|
||||||
|
'current_page': None, # Current page number
|
||||||
|
|
||||||
|
# Top process view requirements
|
||||||
|
'top_data': [int], # Top data types needed by memphis core plugin
|
||||||
|
'top_cols': ["%CPU "] # Column names
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get CPU frequency
|
||||||
|
cpu_hz = os.sysconf(2)
|
||||||
|
|
||||||
|
pids_ujiffies = {}
|
48
shell/console/plugins/cpu/info.py
Normal file
48
shell/console/plugins/cpu/info.py
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
###########################################################
|
||||||
|
# Main function:
|
||||||
|
# -----------------
|
||||||
|
# self: self plugin object
|
||||||
|
# mself: memphis object / principal class
|
||||||
|
# pinfo: row with information about current tracing process
|
||||||
|
############################################################
|
||||||
|
|
||||||
|
def plg_on_top_data_refresh(self, pinfo):
|
||||||
|
PI = self.INTERNALS['Plg'].proc
|
||||||
|
|
||||||
|
pid = pinfo['pid']
|
||||||
|
|
||||||
|
# Get JIFFIES CPU usage
|
||||||
|
used_jiffies = pinfo['utime'] + pinfo['stime']
|
||||||
|
last_ujiffies = get_pid_ujiffies(self, pid)
|
||||||
|
|
||||||
|
cpu_usage = PI.get_CPU_usage(self.cpu_hz, used_jiffies, pinfo['start_time'])
|
||||||
|
|
||||||
|
# Get PERCENT CPU usage
|
||||||
|
if last_ujiffies == 0.0:
|
||||||
|
pcpu = 0.0
|
||||||
|
set_pid_ujiffies(self, pid, cpu_usage['used_jiffies'])
|
||||||
|
data = [int(pcpu)]
|
||||||
|
return data
|
||||||
|
|
||||||
|
used_jiffies = cpu_usage['used_jiffies'] - last_ujiffies
|
||||||
|
|
||||||
|
# Available jiffies are
|
||||||
|
avail_jiffies = (500/1000.0)*self.cpu_hz # 500 = 0.5 second
|
||||||
|
pcpu = ((used_jiffies*100)/avail_jiffies)
|
||||||
|
|
||||||
|
set_pid_ujiffies(self, pid, cpu_usage['used_jiffies'])
|
||||||
|
|
||||||
|
data = [int(pcpu)]
|
||||||
|
return data
|
||||||
|
|
||||||
|
def get_pid_ujiffies(self, pid):
|
||||||
|
|
||||||
|
if pid in self.pids_ujiffies:
|
||||||
|
return self.pids_ujiffies[pid]
|
||||||
|
else:
|
||||||
|
set_pid_ujiffies(self, pid, 0)
|
||||||
|
return self.pids_ujiffies[pid]
|
||||||
|
|
||||||
|
def set_pid_ujiffies(self, pid, ujiffies):
|
||||||
|
self.pids_ujiffies[pid] = ujiffies
|
||||||
|
|
6
shell/console/plugins/dirty_size/Makefile.am
Normal file
6
shell/console/plugins/dirty_size/Makefile.am
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
sugardir = $(pkgdatadir)/shell/console/plugins/dirty_size
|
||||||
|
sugar_PYTHON = \
|
||||||
|
README \
|
||||||
|
__init__.py \
|
||||||
|
info.py
|
2
shell/console/plugins/dirty_size/README
Normal file
2
shell/console/plugins/dirty_size/README
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
This plugin give support to get the public and shared dirty memory usage
|
||||||
|
by process using the /proc/PID/smaps file.
|
17
shell/console/plugins/dirty_size/__init__.py
Normal file
17
shell/console/plugins/dirty_size/__init__.py
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
|
||||||
|
import info
|
||||||
|
|
||||||
|
|
||||||
|
INTERNALS = {
|
||||||
|
# Basic information
|
||||||
|
'PLGNAME': "Dirty Size",
|
||||||
|
'TABNAME': None, # No tabbed plugin
|
||||||
|
'AUTHOR': "Eduardo Silva",
|
||||||
|
'DESC': "Get dirty size memory usage",
|
||||||
|
|
||||||
|
# Plugin API
|
||||||
|
'Plg': None, # Plugin object
|
||||||
|
|
||||||
|
'top_data': [int], # Top data types needed by memphis core plugin
|
||||||
|
'top_cols': ["PDRSS (kb)"]
|
||||||
|
}
|
20
shell/console/plugins/dirty_size/info.py
Normal file
20
shell/console/plugins/dirty_size/info.py
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
###########################################################
|
||||||
|
# Main function:
|
||||||
|
# -----------------
|
||||||
|
# self: self plugin object
|
||||||
|
# mself: memphis object / principal class
|
||||||
|
# pinfo: row with information about current tracing process
|
||||||
|
############################################################
|
||||||
|
|
||||||
|
|
||||||
|
def plg_on_top_data_refresh(self, ppinfo):
|
||||||
|
|
||||||
|
dirty_sizes = get_dirty(self, ppinfo['pid'])
|
||||||
|
|
||||||
|
# memhis need an array
|
||||||
|
return [dirty_sizes['private']]
|
||||||
|
|
||||||
|
def get_dirty(pself, pid):
|
||||||
|
ProcAnalysis = pself.INTERNALS['Plg'].proc_analysis(pid)
|
||||||
|
|
||||||
|
return ProcAnalysis.DirtyRSS()
|
6
shell/console/plugins/memphis_init/Makefile.am
Normal file
6
shell/console/plugins/memphis_init/Makefile.am
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
sugardir = $(pkgdatadir)/shell/console/plugins/memphis_init
|
||||||
|
sugar_PYTHON = \
|
||||||
|
README \
|
||||||
|
__init__.py \
|
||||||
|
info.py
|
2
shell/console/plugins/memphis_init/README
Normal file
2
shell/console/plugins/memphis_init/README
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
This plugin give support to draw the Virtual Memory Size
|
||||||
|
usage by the current tracing process.
|
15
shell/console/plugins/memphis_init/__init__.py
Normal file
15
shell/console/plugins/memphis_init/__init__.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import info
|
||||||
|
|
||||||
|
INTERNALS = {
|
||||||
|
'PLGNAME': "memphis",
|
||||||
|
'TABNAME': None,
|
||||||
|
'AUTHOR': "Eduardo Silva",
|
||||||
|
'DESC': "Print basic process information",
|
||||||
|
|
||||||
|
# Plugin API
|
||||||
|
'Plg': None, # Plugin object
|
||||||
|
|
||||||
|
# Top process view requirements
|
||||||
|
'top_data': [int, str, str], # Top data types needed by memphis core plugin
|
||||||
|
'top_cols': ["PID", "Process Name", "Status"] # Column names
|
||||||
|
}
|
13
shell/console/plugins/memphis_init/info.py
Normal file
13
shell/console/plugins/memphis_init/info.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
###########################################################
|
||||||
|
# Main function:
|
||||||
|
# -----------------
|
||||||
|
# self: self plugin object
|
||||||
|
# mself: memphis object / principal class
|
||||||
|
# pinfo: row with information about current tracing process
|
||||||
|
############################################################
|
||||||
|
|
||||||
|
def plg_on_top_data_refresh(self, ppinfo):
|
||||||
|
|
||||||
|
data = [ppinfo['pid'], ppinfo['name'], ppinfo['state_name']]
|
||||||
|
|
||||||
|
return data
|
8
shell/console/procmem/Makefile.am
Normal file
8
shell/console/procmem/Makefile.am
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
sugardir = $(pkgdatadir)/shell/console/procmem
|
||||||
|
|
||||||
|
sugar_PYTHON = \
|
||||||
|
__init__.py \
|
||||||
|
proc.py \
|
||||||
|
proc_smaps.py \
|
||||||
|
analysis.py
|
0
shell/console/procmem/__init__.py
Normal file
0
shell/console/procmem/__init__.py
Normal file
30
shell/console/procmem/analysis.py
Normal file
30
shell/console/procmem/analysis.py
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import proc, proc_smaps
|
||||||
|
|
||||||
|
class Analysis:
|
||||||
|
|
||||||
|
pid = 0
|
||||||
|
|
||||||
|
def __init__(self, pid):
|
||||||
|
self.pid = pid
|
||||||
|
|
||||||
|
def DirtyRSS(self):
|
||||||
|
smaps = proc_smaps.ProcSmaps(self.pid)
|
||||||
|
dirty = []
|
||||||
|
|
||||||
|
private = 0
|
||||||
|
shared = 0
|
||||||
|
|
||||||
|
for map in smaps.mappings:
|
||||||
|
private += map.private_dirty
|
||||||
|
shared += map.shared_dirty
|
||||||
|
|
||||||
|
dirty = {"private": int(private), "shared": int(shared)}
|
||||||
|
|
||||||
|
return dirty
|
||||||
|
|
||||||
|
def ApproxRealMemoryUsage(self):
|
||||||
|
maps = proc_smaps.ProcMaps(self.pid)
|
||||||
|
size = (maps.clean_size/1024)
|
||||||
|
|
||||||
|
return size
|
||||||
|
|
100
shell/console/procmem/proc.py
Normal file
100
shell/console/procmem/proc.py
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import sys, os
|
||||||
|
import string
|
||||||
|
|
||||||
|
class ProcInfo:
|
||||||
|
|
||||||
|
dir_path = "/proc/" # Our cute Proc File System
|
||||||
|
status_file = "status"
|
||||||
|
stat_file = "stat"
|
||||||
|
|
||||||
|
proc_list = [] # Our PID list :D
|
||||||
|
proc_info = [] #
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.proc_list = self.Get_PID_List()
|
||||||
|
|
||||||
|
# Returns Process List
|
||||||
|
def Get_PID_List(self):
|
||||||
|
list = []
|
||||||
|
|
||||||
|
# Exists our procfs ?
|
||||||
|
if os.path.isdir(self.dir_path):
|
||||||
|
# around dir entries
|
||||||
|
for f in os.listdir(self.dir_path):
|
||||||
|
if os.path.isdir(self.dir_path+f) & str.isdigit(f):
|
||||||
|
list.append(int(f))
|
||||||
|
|
||||||
|
return list
|
||||||
|
|
||||||
|
def MemoryInfo(self, pid):
|
||||||
|
# Path
|
||||||
|
pidfile = self.dir_path + str(pid) + "/stat"
|
||||||
|
try:
|
||||||
|
infile = open(pidfile, "r")
|
||||||
|
except:
|
||||||
|
print "Error trying " + pidfile
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Parsing data , check 'man 5 proc' for details
|
||||||
|
data = infile.read().split()
|
||||||
|
|
||||||
|
infile.close()
|
||||||
|
|
||||||
|
state_dic = {
|
||||||
|
'R': 'Running',
|
||||||
|
'S': 'Sleeping',
|
||||||
|
'D': 'Disk sleep',
|
||||||
|
'Z': 'Zombie',
|
||||||
|
'T': 'Traced/Stopped',
|
||||||
|
'W': 'Paging'
|
||||||
|
}
|
||||||
|
|
||||||
|
# user and group owners
|
||||||
|
pidstat = os.stat(pidfile)
|
||||||
|
|
||||||
|
info = {
|
||||||
|
'pid': int(data[0]), # Process ID
|
||||||
|
'name': data[1].strip('()'), # Process name
|
||||||
|
'state': data[2], # Process State, ex: R|S|D|Z|T|W
|
||||||
|
'state_name': state_dic[data[2]], # Process State name, ex: Running, sleeping, Zombie, etc
|
||||||
|
'ppid': int(data[3]), # Parent process ID
|
||||||
|
'utime': int(data[13]), # Used jiffies in user mode
|
||||||
|
'stime': int(data[14]), # Used jiffies in kernel mode
|
||||||
|
'start_time': int(data[21]), # Process time from system boot (jiffies)
|
||||||
|
'vsize': int(data[22]), # Virtual memory size used (bytes)
|
||||||
|
'rss': int(data[23])*4, # Resident Set Size (bytes)
|
||||||
|
'user_id': pidstat.st_uid, # process owner
|
||||||
|
'group_id': pidstat.st_gid # owner group
|
||||||
|
}
|
||||||
|
|
||||||
|
return info
|
||||||
|
|
||||||
|
|
||||||
|
# Returns the CPU usage expressed in Jiffies
|
||||||
|
def get_CPU_usage(self, cpu_hz, used_jiffies, start_time):
|
||||||
|
|
||||||
|
# Uptime info
|
||||||
|
uptime_file = self.dir_path + "/uptime"
|
||||||
|
try:
|
||||||
|
infile = file(uptime_file, "r")
|
||||||
|
except:
|
||||||
|
print "Error trying uptime file"
|
||||||
|
return None
|
||||||
|
|
||||||
|
uptime_line = infile.readline()
|
||||||
|
uptime = string.split(uptime_line, " ",2)
|
||||||
|
|
||||||
|
infile.close()
|
||||||
|
|
||||||
|
# System uptime, from /proc/uptime
|
||||||
|
uptime = float(uptime[0])
|
||||||
|
|
||||||
|
# Jiffies
|
||||||
|
avail_jiffies = (uptime * cpu_hz) - start_time
|
||||||
|
|
||||||
|
cpu_usage = {'used_jiffies': used_jiffies, 'avail_jiffies': avail_jiffies}
|
||||||
|
|
||||||
|
return cpu_usage
|
||||||
|
|
129
shell/console/procmem/proc_smaps.py
Normal file
129
shell/console/procmem/proc_smaps.py
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
####################################################################
|
||||||
|
# This class open the /proc/PID/maps and /proc/PID/smaps files
|
||||||
|
# to get useful information about the real memory usage
|
||||||
|
####################################################################
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
# Parse the /proc/PID/smaps file
|
||||||
|
class ProcSmaps:
|
||||||
|
|
||||||
|
mappings = [] # Devices information
|
||||||
|
|
||||||
|
def __init__(self, pid):
|
||||||
|
|
||||||
|
smapfile = "/proc/%s/smaps" % pid
|
||||||
|
self.mappings = []
|
||||||
|
|
||||||
|
# Coded by Federico Mena (script)
|
||||||
|
try:
|
||||||
|
infile = open(smapfile, "r")
|
||||||
|
input = infile.read()
|
||||||
|
infile.close()
|
||||||
|
except:
|
||||||
|
print "Error trying " + smapfile
|
||||||
|
return
|
||||||
|
|
||||||
|
lines = input.splitlines()
|
||||||
|
|
||||||
|
num_lines = len (lines)
|
||||||
|
line_idx = 0
|
||||||
|
|
||||||
|
# 08065000-08067000 rw-p 0001c000 03:01 147613 /opt/gnome/bin/evolution-2.6
|
||||||
|
# Size: 8 kB
|
||||||
|
# Rss: 8 kB
|
||||||
|
# Shared_Clean: 0 kB
|
||||||
|
# Shared_Dirty: 0 kB
|
||||||
|
# Private_Clean: 8 kB
|
||||||
|
# Private_Dirty: 0 kB
|
||||||
|
|
||||||
|
while num_lines > 0:
|
||||||
|
fields = lines[line_idx].split (" ", 5)
|
||||||
|
if len (fields) == 6:
|
||||||
|
(offsets, permissions, bin_permissions, device, inode, name) = fields
|
||||||
|
else:
|
||||||
|
(offsets, permissions, bin_permissions, device, inode) = fields
|
||||||
|
name = ""
|
||||||
|
|
||||||
|
size = self.parse_smaps_size_line (lines[line_idx + 1])
|
||||||
|
rss = self.parse_smaps_size_line (lines[line_idx + 2])
|
||||||
|
shared_clean = self.parse_smaps_size_line (lines[line_idx + 3])
|
||||||
|
shared_dirty = self.parse_smaps_size_line (lines[line_idx + 4])
|
||||||
|
private_clean = self.parse_smaps_size_line (lines[line_idx + 5])
|
||||||
|
private_dirty = self.parse_smaps_size_line (lines[line_idx + 6])
|
||||||
|
name = name.strip ()
|
||||||
|
|
||||||
|
mapping = Mapping (size, rss, shared_clean, shared_dirty, private_clean, private_dirty, permissions, name)
|
||||||
|
self.mappings.append (mapping)
|
||||||
|
|
||||||
|
num_lines -= 7
|
||||||
|
line_idx += 7
|
||||||
|
|
||||||
|
# Parses a line of the form "foo: 42 kB" and returns an integer for the "42" field
|
||||||
|
def parse_smaps_size_line (self, line):
|
||||||
|
# Rss: 8 kB
|
||||||
|
fields = line.split ()
|
||||||
|
return int(fields[1])
|
||||||
|
|
||||||
|
class Mapping:
|
||||||
|
def __init__ (self, size, rss, shared_clean, shared_dirty, private_clean, private_dirty, permissions, name):
|
||||||
|
self.size = size
|
||||||
|
self.rss = rss
|
||||||
|
self.shared_clean = shared_clean
|
||||||
|
self.shared_dirty = shared_dirty
|
||||||
|
self.private_clean = private_clean
|
||||||
|
self.private_dirty = private_dirty
|
||||||
|
self.permissions = permissions
|
||||||
|
self.name = name
|
||||||
|
|
||||||
|
# Parse /proc/PID/maps file to get the clean memory usage by process,
|
||||||
|
# we avoid lines with backed-files
|
||||||
|
class ProcMaps:
|
||||||
|
|
||||||
|
clean_size = 0
|
||||||
|
|
||||||
|
def __init__(self, pid):
|
||||||
|
mapfile = "/proc/%s/maps" % pid
|
||||||
|
|
||||||
|
try:
|
||||||
|
infile = open(mapfile, "r")
|
||||||
|
except:
|
||||||
|
print "Error trying " + mapfile
|
||||||
|
return None
|
||||||
|
|
||||||
|
sum = 0
|
||||||
|
to_data_do = {
|
||||||
|
"[anon]": self.parse_size_line,
|
||||||
|
"[heap]": self.parse_size_line
|
||||||
|
}
|
||||||
|
|
||||||
|
for line in infile:
|
||||||
|
arr = line.split()
|
||||||
|
|
||||||
|
# Just parse writable mapped areas
|
||||||
|
if arr[1][1] != "w":
|
||||||
|
continue
|
||||||
|
|
||||||
|
if len(arr) == 6:
|
||||||
|
# if we got a backed-file we skip this info
|
||||||
|
if os.path.isfile(arr[5]):
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
line_size = to_data_do.get(arr[5], self.skip)(line)
|
||||||
|
sum += line_size
|
||||||
|
else:
|
||||||
|
line_size = self.parse_size_line(line)
|
||||||
|
sum += line_size
|
||||||
|
|
||||||
|
infile.close()
|
||||||
|
self.clean_size = sum
|
||||||
|
|
||||||
|
def skip(self, line):
|
||||||
|
return 0
|
||||||
|
|
||||||
|
# Parse a maps line and return the mapped size
|
||||||
|
def parse_size_line(self, line):
|
||||||
|
start, end = line.split()[0].split('-')
|
||||||
|
size = int(end, 16) - int(start, 16)
|
||||||
|
return size
|
143
shell/console/terminal.py
Normal file
143
shell/console/terminal.py
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
import gtk
|
||||||
|
import vte
|
||||||
|
import pango
|
||||||
|
|
||||||
|
class Terminal(gtk.HBox):
|
||||||
|
def __init__(self):
|
||||||
|
gtk.HBox.__init__(self, False, 4)
|
||||||
|
|
||||||
|
self._vte = vte.Terminal()
|
||||||
|
self._configure_vte()
|
||||||
|
self._vte.set_size(30, 5)
|
||||||
|
self._vte.set_size_request(200, 450)
|
||||||
|
self._vte.show()
|
||||||
|
self.pack_start(self._vte)
|
||||||
|
|
||||||
|
self._scrollbar = gtk.VScrollbar(self._vte.get_adjustment())
|
||||||
|
self._scrollbar.show()
|
||||||
|
self.pack_start(self._scrollbar, False, False, 0)
|
||||||
|
|
||||||
|
self._vte.connect("child-exited", lambda term: term.fork_command())
|
||||||
|
|
||||||
|
self._vte.fork_command()
|
||||||
|
|
||||||
|
def _configure_vte(self):
|
||||||
|
self._vte.set_font(pango.FontDescription('Monospace 10'))
|
||||||
|
self._vte.set_colors(gtk.gdk.color_parse ('#AAAAAA'),
|
||||||
|
gtk.gdk.color_parse ('#000000'),
|
||||||
|
[])
|
||||||
|
self._vte.set_cursor_blinks(False)
|
||||||
|
self._vte.set_audible_bell(False)
|
||||||
|
self._vte.set_scrollback_lines(100)
|
||||||
|
self._vte.set_allow_bold(True)
|
||||||
|
self._vte.set_scroll_on_keystroke(False)
|
||||||
|
self._vte.set_scroll_on_output(False)
|
||||||
|
self._vte.set_emulation('xterm')
|
||||||
|
self._vte.set_visible_bell(False)
|
||||||
|
|
||||||
|
def on_gconf_notification(self, client, cnxn_id, entry, what):
|
||||||
|
self.reconfigure_vte()
|
||||||
|
|
||||||
|
def on_vte_button_press(self, term, event):
|
||||||
|
if event.button == 3:
|
||||||
|
self.do_popup(event)
|
||||||
|
return True
|
||||||
|
|
||||||
|
def on_vte_popup_menu(self, term):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class Multiple:
|
||||||
|
|
||||||
|
page_number = 0
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.notebook = gtk.Notebook()
|
||||||
|
self.add_new_terminal()
|
||||||
|
|
||||||
|
open_terminal = gtk.Button('Open a new terminal')
|
||||||
|
open_terminal.connect("clicked", self.add_new_terminal)
|
||||||
|
open_terminal.show()
|
||||||
|
|
||||||
|
self.notebook.show()
|
||||||
|
|
||||||
|
self.main_vbox = gtk.VBox(False, 3)
|
||||||
|
self.main_vbox.pack_start(open_terminal, True, True, 2)
|
||||||
|
self.main_vbox.pack_start(self.notebook, True, True, 2)
|
||||||
|
|
||||||
|
self.main_vbox.show_all()
|
||||||
|
|
||||||
|
# Remove a page from the notebook
|
||||||
|
def close_terminal(self, button, child):
|
||||||
|
page = self.notebook.page_num(child)
|
||||||
|
|
||||||
|
if page != -1:
|
||||||
|
self.notebook.remove_page(page)
|
||||||
|
|
||||||
|
|
||||||
|
pages = self.notebook.get_n_pages()
|
||||||
|
if pages <= 0:
|
||||||
|
self.page_number = 0
|
||||||
|
self.add_new_terminal()
|
||||||
|
|
||||||
|
# Need to refresh the widget --
|
||||||
|
# This forces the widget to redraw itself.
|
||||||
|
self.notebook.queue_draw_area(0, 0, -1, -1)
|
||||||
|
|
||||||
|
def add_icon_to_button(self, button):
|
||||||
|
iconBox = gtk.HBox(False, 0)
|
||||||
|
image = gtk.Image()
|
||||||
|
image.set_from_stock(gtk.STOCK_CLOSE, gtk.ICON_SIZE_MENU)
|
||||||
|
gtk.Button.set_relief(button, gtk.RELIEF_NONE)
|
||||||
|
|
||||||
|
settings = gtk.Widget.get_settings (button)
|
||||||
|
(w,h) = gtk.icon_size_lookup_for_settings (settings, gtk.ICON_SIZE_MENU)
|
||||||
|
gtk.Widget.set_size_request (button, w + 4, h + 4)
|
||||||
|
image.show()
|
||||||
|
iconBox.pack_start(image, True, False, 0)
|
||||||
|
button.add(iconBox)
|
||||||
|
iconBox.show()
|
||||||
|
|
||||||
|
def add_new_terminal(self, *arguments, **keywords):
|
||||||
|
self.page_number += 1
|
||||||
|
|
||||||
|
terminal = Terminal()
|
||||||
|
terminal.show()
|
||||||
|
|
||||||
|
eventBox = self.create_custom_tab("Term %d" % self.page_number, terminal)
|
||||||
|
self.notebook.append_page(terminal, eventBox)
|
||||||
|
|
||||||
|
# Set the new page
|
||||||
|
pages = gtk.Notebook.get_n_pages(self.notebook)
|
||||||
|
self.notebook.set_current_page(pages - 1)
|
||||||
|
return True
|
||||||
|
|
||||||
|
def create_custom_tab(self, text, child):
|
||||||
|
eventBox = gtk.EventBox()
|
||||||
|
tabBox = gtk.HBox(False, 2)
|
||||||
|
tabLabel = gtk.Label(text)
|
||||||
|
|
||||||
|
tabButton = gtk.Button()
|
||||||
|
tabButton.connect('clicked', self.close_terminal, child)
|
||||||
|
|
||||||
|
# Add a picture on a button
|
||||||
|
self.add_icon_to_button(tabButton)
|
||||||
|
iconBox = gtk.HBox(False, 0)
|
||||||
|
|
||||||
|
eventBox.show()
|
||||||
|
tabButton.show()
|
||||||
|
tabLabel.show()
|
||||||
|
|
||||||
|
tabBox.pack_start(tabLabel, False)
|
||||||
|
tabBox.pack_start(tabButton, False)
|
||||||
|
|
||||||
|
tabBox.show_all()
|
||||||
|
eventBox.add(tabBox)
|
||||||
|
|
||||||
|
return eventBox
|
||||||
|
|
||||||
|
class Interface:
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
multiple = Multiple()
|
||||||
|
self.widget = multiple.main_vbox
|
||||||
|
|
@ -6,6 +6,6 @@
|
|||||||
<Alt>p=prev
|
<Alt>p=prev
|
||||||
<Alt>c=close
|
<Alt>c=close
|
||||||
|
|
||||||
<Alt><Shift>F12=!sugar-log-viewer
|
<Alt><Shift>F12=!sugar-devel-console
|
||||||
<Alt>q=!sugar-emulator-shutdown
|
<Alt>q=!sugar-emulator-shutdown
|
||||||
<Alt><Shift>Escape=!sugar-shutdown
|
<Alt><Shift>Escape=!sugar-shutdown
|
||||||
|
12
shell/sugar-devel-console
Executable file
12
shell/sugar-devel-console
Executable file
@ -0,0 +1,12 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
# Sugar developer console launcher
|
||||||
|
import pygtk
|
||||||
|
pygtk.require('2.0')
|
||||||
|
|
||||||
|
import os, sys
|
||||||
|
from sugar import env
|
||||||
|
|
||||||
|
sys.path.insert(0, os.path.join(env.get_data_dir(), 'shell'))
|
||||||
|
|
||||||
|
import console.console
|
@ -76,11 +76,6 @@ for i in range(1, len(sys.argv)):
|
|||||||
emulator = Emulator(fullscreen)
|
emulator = Emulator(fullscreen)
|
||||||
emulator.start()
|
emulator.start()
|
||||||
|
|
||||||
if env.get_dbus_version() < '0.95':
|
|
||||||
if not os.path.isdir('/tmp/sugar-services'):
|
|
||||||
os.mkdir('/tmp/sugar-services')
|
|
||||||
dbus_config = env.get_dbus_config_094()
|
|
||||||
else:
|
|
||||||
dbus_config = env.get_dbus_config()
|
dbus_config = env.get_dbus_config()
|
||||||
|
|
||||||
os.execlp('dbus-launch', 'dbus-launch', '--exit-with-session',
|
os.execlp('dbus-launch', 'dbus-launch', '--exit-with-session',
|
||||||
|
@ -4,5 +4,4 @@ sugar_activities_dir = '@prefix@/share/sugar/activities'
|
|||||||
sugar_activity_info_dir = '@prefix@/share/sugar/activities'
|
sugar_activity_info_dir = '@prefix@/share/sugar/activities'
|
||||||
sugar_services_dir = '@prefix@/share/sugar/services'
|
sugar_services_dir = '@prefix@/share/sugar/services'
|
||||||
sugar_dbus_config = '@prefix@/share/sugar/dbus-installed.conf'
|
sugar_dbus_config = '@prefix@/share/sugar/dbus-installed.conf'
|
||||||
sugar_dbus_config_094 = '@prefix@/share/sugar/dbus-installed-094.conf'
|
|
||||||
sugar_shell_bin_dir = '@prefix@/bin'
|
sugar_shell_bin_dir = '@prefix@/bin'
|
||||||
|
@ -9,5 +9,4 @@ sugar_services_dir = os.path.join(_sourcedir, 'services')
|
|||||||
sugar_activity_info_dir = _tmpdir
|
sugar_activity_info_dir = _tmpdir
|
||||||
sugar_activities_dir = os.path.join(_sourcedir, 'activities')
|
sugar_activities_dir = os.path.join(_sourcedir, 'activities')
|
||||||
sugar_dbus_config = os.path.join(_sourcedir, 'dbus-uninstalled.conf')
|
sugar_dbus_config = os.path.join(_sourcedir, 'dbus-uninstalled.conf')
|
||||||
sugar_dbus_config_094 = os.path.join(_sourcedir, 'dbus-uninstalled-094.conf')
|
|
||||||
sugar_shell_bin_dir = os.path.join(_sourcedir, 'shell')
|
sugar_shell_bin_dir = os.path.join(_sourcedir, 'shell')
|
||||||
|
@ -100,6 +100,7 @@ class Activity(gtk.Window):
|
|||||||
|
|
||||||
bus = dbus.SessionBus()
|
bus = dbus.SessionBus()
|
||||||
xid = self.window.xid
|
xid = self.window.xid
|
||||||
|
|
||||||
bus_name = dbus.service.BusName(get_service_name(xid), bus=bus)
|
bus_name = dbus.service.BusName(get_service_name(xid), bus=bus)
|
||||||
self._bus = ActivityDbusService(bus_name, get_object_path(xid))
|
self._bus = ActivityDbusService(bus_name, get_object_path(xid))
|
||||||
self._bus.start(self._pservice, self)
|
self._bus.start(self._pservice, self)
|
||||||
|
@ -10,11 +10,7 @@ class _ServiceParser(ConfigParser):
|
|||||||
|
|
||||||
class _ServiceManager(object):
|
class _ServiceManager(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
if env.get_dbus_version() < '0.95':
|
|
||||||
self._path = '/tmp/sugar-services'
|
|
||||||
else:
|
|
||||||
self._path = os.path.expanduser('~/.local/share/dbus-1/services')
|
self._path = os.path.expanduser('~/.local/share/dbus-1/services')
|
||||||
|
|
||||||
if not os.path.isdir(self._path):
|
if not os.path.isdir(self._path):
|
||||||
os.makedirs(self._path)
|
os.makedirs(self._path)
|
||||||
|
|
||||||
|
@ -54,9 +54,6 @@ def get_services_dir():
|
|||||||
def get_dbus_config():
|
def get_dbus_config():
|
||||||
return sugar_dbus_config
|
return sugar_dbus_config
|
||||||
|
|
||||||
def get_dbus_config_094():
|
|
||||||
return sugar_dbus_config_094
|
|
||||||
|
|
||||||
def get_shell_bin_dir():
|
def get_shell_bin_dir():
|
||||||
return sugar_shell_bin_dir
|
return sugar_shell_bin_dir
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user