summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorjhawkins@chromium.org <jhawkins@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-01 16:31:07 +0000
committerjhawkins@chromium.org <jhawkins@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-01 16:31:07 +0000
commit48c17f3fd63823010d7af9f5ff9832880eed1fcb (patch)
treed1b287446ee3d98b3fad6cdbc00c7ac61fc13252 /chrome
parent011479016795f1dd436f81849a21fd8d6ff65ce3 (diff)
downloadchromium_src-48c17f3fd63823010d7af9f5ff9832880eed1fcb.zip
chromium_src-48c17f3fd63823010d7af9f5ff9832880eed1fcb.tar.gz
chromium_src-48c17f3fd63823010d7af9f5ff9832880eed1fcb.tar.bz2
Implement the core functionality of the gtk task manager.
BUG=11392 TEST=none Review URL: http://codereview.chromium.org/151154 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@19738 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/gtk/task_manager_gtk.cc289
-rw-r--r--chrome/browser/gtk/task_manager_gtk.h36
2 files changed, 273 insertions, 52 deletions
diff --git a/chrome/browser/gtk/task_manager_gtk.cc b/chrome/browser/gtk/task_manager_gtk.cc
index 5db60e7..d293ea0 100644
--- a/chrome/browser/gtk/task_manager_gtk.cc
+++ b/chrome/browser/gtk/task_manager_gtk.cc
@@ -21,7 +21,7 @@ const int kDefaultHeight = 270;
// The resource id for the 'End process' button.
const gint kTaskManagerResponseKill = 1;
-enum TaskManagerColumns {
+enum TaskManagerColumn {
kTaskManagerPage,
kTaskManagerPhysicalMem,
kTaskManagerSharedMem,
@@ -29,48 +29,64 @@ enum TaskManagerColumns {
kTaskManagerCPU,
kTaskManagerNetwork,
kTaskManagerProcessID,
+ kTaskManagerGoatsTeleported,
kTaskManagerColumnCount,
};
-void TreeViewColumnSetVisible(GtkWidget* treeview, TaskManagerColumns colid,
+TaskManagerColumn TaskManagerResourceIDToColumnID(int id) {
+ switch (id) {
+ case IDS_TASK_MANAGER_PAGE_COLUMN:
+ return kTaskManagerPage;
+ case IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN:
+ return kTaskManagerPhysicalMem;
+ case IDS_TASK_MANAGER_SHARED_MEM_COLUMN:
+ return kTaskManagerSharedMem;
+ case IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN:
+ return kTaskManagerPrivateMem;
+ case IDS_TASK_MANAGER_CPU_COLUMN:
+ return kTaskManagerCPU;
+ case IDS_TASK_MANAGER_NET_COLUMN:
+ return kTaskManagerNetwork;
+ case IDS_TASK_MANAGER_PROCESS_ID_COLUMN:
+ return kTaskManagerProcessID;
+ default:
+ NOTREACHED();
+ return static_cast<TaskManagerColumn>(-1);
+ }
+}
+
+// Shows or hides a treeview column.
+void TreeViewColumnSetVisible(GtkWidget* treeview, TaskManagerColumn colid,
bool visible) {
GtkTreeViewColumn* column = gtk_tree_view_get_column(GTK_TREE_VIEW(treeview),
colid);
gtk_tree_view_column_set_visible(column, visible);
}
-void TreeViewInsertColumn(GtkWidget* treeview,
- TaskManagerColumns colid, int str) {
+// Inserts a column with a column id of |colid| and |name|.
+void TreeViewInsertColumnWithName(GtkWidget* treeview,
+ int colid, const char* name) {
GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(treeview), -1,
- l10n_util::GetStringUTF8(str).c_str(),
- renderer, "text", colid, NULL);
+ name, renderer, "text",
+ colid, NULL);
}
-GtkWidget* CreateTaskManagerTreeview() {
- GtkWidget* treeview = gtk_tree_view_new();
-
- TreeViewInsertColumn(treeview, kTaskManagerPage,
- IDS_TASK_MANAGER_PAGE_COLUMN);
- TreeViewInsertColumn(treeview, kTaskManagerPhysicalMem,
- IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN);
- TreeViewInsertColumn(treeview, kTaskManagerSharedMem,
- IDS_TASK_MANAGER_SHARED_MEM_COLUMN);
- TreeViewInsertColumn(treeview, kTaskManagerPrivateMem,
- IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN);
- TreeViewInsertColumn(treeview, kTaskManagerCPU,
- IDS_TASK_MANAGER_CPU_COLUMN);
- TreeViewInsertColumn(treeview, kTaskManagerNetwork,
- IDS_TASK_MANAGER_NET_COLUMN);
- TreeViewInsertColumn(treeview, kTaskManagerProcessID,
- IDS_TASK_MANAGER_PROCESS_ID_COLUMN);
-
- GtkListStore* store = gtk_list_store_new(kTaskManagerColumnCount,
- G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT,
- G_TYPE_STRING, G_TYPE_UINT);
+// Loads the column name from |resid| and uses the corresponding
+// TaskManagerColumn value as the column id to insert into the treeview.
+void TreeViewInsertColumn(GtkWidget* treeview, int resid) {
+ TreeViewInsertColumnWithName(treeview, TaskManagerResourceIDToColumnID(resid),
+ l10n_util::GetStringUTF8(resid).c_str());
+}
- gtk_tree_view_set_model(GTK_TREE_VIEW(treeview), GTK_TREE_MODEL(store));
- return treeview;
+// Get the row number corresponding to |path|.
+gint GetRowNumForPath(GtkTreePath* path) {
+ gint* indices = gtk_tree_path_get_indices(path);
+ if (!indices) {
+ NOTREACHED();
+ return -1;
+ }
+ return indices[0];
}
} // namespace
@@ -79,7 +95,9 @@ TaskManagerGtk::TaskManagerGtk()
: task_manager_(TaskManager::GetInstance()),
model_(TaskManager::GetInstance()->model()),
dialog_(NULL),
- treeview_(NULL) {
+ treeview_(NULL),
+ process_list_(NULL),
+ process_count_(0) {
Init();
}
@@ -87,8 +105,80 @@ TaskManagerGtk::TaskManagerGtk()
TaskManagerGtk* TaskManagerGtk::instance_ = NULL;
TaskManagerGtk::~TaskManagerGtk() {
+ task_manager_->OnWindowClosed();
}
+////////////////////////////////////////////////////////////////////////////////
+// TaskManagerGtk, TaskManagerModelObserver implementation:
+
+void TaskManagerGtk::OnModelChanged() {
+ // Nothing to do.
+}
+
+void TaskManagerGtk::OnItemsChanged(int start, int length) {
+ GtkTreeIter iter;
+ gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(process_list_), &iter,
+ NULL, start);
+
+ for (int i = start; i < start + length; i++) {
+ SetRowDataFromModel(i, &iter);
+ gtk_tree_model_iter_next(GTK_TREE_MODEL(process_list_), &iter);
+ }
+}
+
+void TaskManagerGtk::OnItemsAdded(int start, int length) {
+ GtkTreeIter iter;
+ if (start == 0) {
+ gtk_list_store_prepend(process_list_, &iter);
+ } else if (start >= process_count_) {
+ gtk_list_store_append(process_list_, &iter);
+ } else {
+ GtkTreeIter sibling;
+ gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(process_list_), &sibling,
+ NULL, start);
+ gtk_list_store_insert_before(process_list_, &iter, &sibling);
+ }
+
+ SetRowDataFromModel(start, &iter);
+
+ for (int i = start + 1; i < start + length; i++) {
+ gtk_list_store_insert_after(process_list_, &iter, &iter);
+ SetRowDataFromModel(i, &iter);
+ }
+
+ process_count_ += length;
+}
+
+void TaskManagerGtk::OnItemsRemoved(int start, int length) {
+ GtkTreeIter iter;
+ gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(process_list_), &iter,
+ NULL, start);
+
+ for (int i = 0; i < length; i++) {
+ // |iter| is moved to the next valid node when the current node is removed.
+ gtk_list_store_remove(process_list_, &iter);
+ }
+
+ process_count_ -= length;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// TaskManagerGtk, public:
+
+// static
+void TaskManagerGtk::Show() {
+ if (instance_) {
+ // If there's a Task manager window open already, just activate it.
+ gtk_window_present(GTK_WINDOW(instance_->dialog_));
+ } else {
+ instance_ = new TaskManagerGtk;
+ instance_->model_->StartUpdating();
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// TaskManagerGtk, private:
+
void TaskManagerGtk::Init() {
dialog_ = gtk_dialog_new_with_buttons(
l10n_util::GetStringUTF8(IDS_TASK_MANAGER_TITLE).c_str(),
@@ -104,7 +194,7 @@ void TaskManagerGtk::Init() {
g_signal_connect(G_OBJECT(dialog_), "response", G_CALLBACK(OnResponse), this);
- treeview_ = CreateTaskManagerTreeview();
+ CreateTaskManagerTreeview();
gtk_tree_view_set_headers_clickable(GTK_TREE_VIEW(treeview_), TRUE);
gtk_tree_view_set_grid_lines(GTK_TREE_VIEW(treeview_),
GTK_TREE_VIEW_GRID_LINES_HORIZONTAL);
@@ -113,29 +203,121 @@ void TaskManagerGtk::Init() {
TreeViewColumnSetVisible(treeview_, kTaskManagerSharedMem, false);
TreeViewColumnSetVisible(treeview_, kTaskManagerPrivateMem, false);
TreeViewColumnSetVisible(treeview_, kTaskManagerProcessID, false);
+ TreeViewColumnSetVisible(treeview_, kTaskManagerGoatsTeleported, false);
+
+ // |selection| is owned by |treeview_|.
+ GtkTreeSelection* selection = gtk_tree_view_get_selection(
+ GTK_TREE_VIEW(treeview_));
+ gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE);
+ g_signal_connect(G_OBJECT(selection), "changed",
+ G_CALLBACK(OnSelectionChanged), this);
gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog_)->vbox), treeview_);
gtk_window_resize(GTK_WINDOW(dialog_), kDefaultWidth, kDefaultHeight);
gtk_widget_show_all(dialog_);
- // TODO(jhawkins): mode_->SetObserver() and implement OnItems*.
+ model_->SetObserver(this);
}
-void TaskManagerGtk::OnModelChanged() {
- NOTIMPLEMENTED();
+void TaskManagerGtk::CreateTaskManagerTreeview() {
+ treeview_ = gtk_tree_view_new();
+
+ TreeViewInsertColumn(treeview_, IDS_TASK_MANAGER_PAGE_COLUMN);
+ TreeViewInsertColumn(treeview_, IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN);
+ TreeViewInsertColumn(treeview_, IDS_TASK_MANAGER_SHARED_MEM_COLUMN);
+ TreeViewInsertColumn(treeview_, IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN);
+ TreeViewInsertColumn(treeview_, IDS_TASK_MANAGER_CPU_COLUMN);
+ TreeViewInsertColumn(treeview_, IDS_TASK_MANAGER_NET_COLUMN);
+ TreeViewInsertColumn(treeview_, IDS_TASK_MANAGER_PROCESS_ID_COLUMN);
+
+ TreeViewInsertColumnWithName(treeview_, kTaskManagerGoatsTeleported,
+ "Goats Teleported");
+
+ process_list_ = gtk_list_store_new(kTaskManagerColumnCount,
+ G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
+ G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+
+ gtk_tree_view_set_model(GTK_TREE_VIEW(treeview_),
+ GTK_TREE_MODEL(process_list_));
+ g_object_unref(process_list_);
}
-void TaskManagerGtk::OnItemsChanged(int start, int length) {
- NOTIMPLEMENTED();
+std::string TaskManagerGtk::GetModelText(int row, int col_id) {
+ switch (col_id) {
+ case IDS_TASK_MANAGER_PAGE_COLUMN: // Process
+ return WideToUTF8(model_->GetResourceTitle(row));
+
+ case IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN: // Memory
+ if (!model_->IsResourceFirstInGroup(row))
+ return std::string();
+ return WideToUTF8(model_->GetResourcePrivateMemory(row));
+
+ case IDS_TASK_MANAGER_SHARED_MEM_COLUMN: // Memory
+ if (!model_->IsResourceFirstInGroup(row))
+ return std::string();
+ return WideToUTF8(model_->GetResourceSharedMemory(row));
+
+ case IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN: // Memory
+ if (!model_->IsResourceFirstInGroup(row))
+ return std::string();
+ return WideToUTF8(model_->GetResourcePhysicalMemory(row));
+
+ case IDS_TASK_MANAGER_CPU_COLUMN: // CPU
+ if (!model_->IsResourceFirstInGroup(row))
+ return std::string();
+ return WideToUTF8(model_->GetResourceCPUUsage(row));
+
+ case IDS_TASK_MANAGER_NET_COLUMN: // Net
+ return WideToUTF8(model_->GetResourceNetworkUsage(row));
+
+ case IDS_TASK_MANAGER_PROCESS_ID_COLUMN: // Process ID
+ if (!model_->IsResourceFirstInGroup(row))
+ return std::string();
+ return WideToUTF8(model_->GetResourceProcessId(row));
+
+ case kTaskManagerGoatsTeleported: // Goats Teleported!
+ return WideToUTF8(model_->GetResourceGoatsTeleported(row));
+
+ default:
+ return WideToUTF8(model_->GetResourceStatsValue(row, col_id));
+ }
}
-void TaskManagerGtk::OnItemsAdded(int start, int length) {
- NOTIMPLEMENTED();
+void TaskManagerGtk::SetRowDataFromModel(int row, GtkTreeIter* iter) {
+ std::string page = GetModelText(row, IDS_TASK_MANAGER_PAGE_COLUMN);
+ std::string phys_mem = GetModelText(
+ row, IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN);
+ std::string shared_mem = GetModelText(
+ row, IDS_TASK_MANAGER_SHARED_MEM_COLUMN);
+ std::string priv_mem = GetModelText(row, IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN);
+ std::string cpu = GetModelText(row, IDS_TASK_MANAGER_CPU_COLUMN);
+ std::string net = GetModelText(row, IDS_TASK_MANAGER_NET_COLUMN);
+ std::string procid = GetModelText(row, IDS_TASK_MANAGER_PROCESS_ID_COLUMN);
+ std::string goats = GetModelText(row, kTaskManagerGoatsTeleported);
+ gtk_list_store_set(process_list_, iter,
+ kTaskManagerPage, page.c_str(),
+ kTaskManagerPhysicalMem, phys_mem.c_str(),
+ kTaskManagerSharedMem, shared_mem.c_str(),
+ kTaskManagerPrivateMem, priv_mem.c_str(),
+ kTaskManagerCPU, cpu.c_str(),
+ kTaskManagerNetwork, net.c_str(),
+ kTaskManagerProcessID, procid.c_str(),
+ kTaskManagerGoatsTeleported, goats.c_str(),
+ -1);
}
-void TaskManagerGtk::OnItemsRemoved(int start, int length) {
- NOTIMPLEMENTED();
+void TaskManagerGtk::KillSelectedProcesses() {
+ GtkTreeSelection* selection = gtk_tree_view_get_selection(
+ GTK_TREE_VIEW(treeview_));
+
+ GtkTreeModel* model;
+ GList* paths = gtk_tree_selection_get_selected_rows(selection, &model);
+ for (GList* item = paths; item; item = item->next) {
+ int row = GetRowNumForPath(reinterpret_cast<GtkTreePath*>(item->data));
+ task_manager_->KillProcess(row);
+ }
+ g_list_free(paths);
}
// static
@@ -143,18 +325,29 @@ void TaskManagerGtk::OnResponse(GtkDialog* dialog, gint response_id,
TaskManagerGtk* task_manager) {
if (response_id == GTK_RESPONSE_DELETE_EVENT) {
instance_ = NULL;
- task_manager->task_manager_->OnWindowClosed();
delete task_manager;
+ } else if (response_id == kTaskManagerResponseKill) {
+ task_manager->KillSelectedProcesses();
}
}
// static
-void TaskManagerGtk::Show() {
- if (instance_) {
- // If there's a Task manager window open already, just activate it.
- gtk_window_present(GTK_WINDOW(instance_->dialog_));
- } else {
- instance_ = new TaskManagerGtk;
- instance_->model_->StartUpdating();
+void TaskManagerGtk::OnSelectionChanged(GtkTreeSelection* selection,
+ TaskManagerGtk* task_manager) {
+ bool selection_contains_browser_process = false;
+
+ GtkTreeModel* model;
+ GList* paths = gtk_tree_selection_get_selected_rows(selection, &model);
+ for (GList* item = paths; item; item = item->next) {
+ int row = GetRowNumForPath(reinterpret_cast<GtkTreePath*>(item->data));
+ if (task_manager->task_manager_->IsBrowserProcess(row)) {
+ selection_contains_browser_process = true;
+ break;
+ }
}
+ g_list_free(paths);
+
+ gtk_dialog_set_response_sensitive(GTK_DIALOG(task_manager->dialog_),
+ kTaskManagerResponseKill,
+ !selection_contains_browser_process);
}
diff --git a/chrome/browser/gtk/task_manager_gtk.h b/chrome/browser/gtk/task_manager_gtk.h
index a2d39bb..53b8bfe 100644
--- a/chrome/browser/gtk/task_manager_gtk.h
+++ b/chrome/browser/gtk/task_manager_gtk.h
@@ -5,6 +5,10 @@
#ifndef CHROME_BROWSER_GTK_TASK_MANAGER_GTK_H_
#define CHROME_BROWSER_GTK_TASK_MANAGER_GTK_H_
+#include <gtk/gtk.h>
+
+#include <string>
+
#include "chrome/browser/task_manager.h"
class TaskManagerGtk : public TaskManagerModelObserver {
@@ -18,17 +22,35 @@ class TaskManagerGtk : public TaskManagerModelObserver {
virtual void OnItemsAdded(int start, int length);
virtual void OnItemsRemoved(int start, int length);
+ // Creates the task manager if it doesn't exist; otherwise, it activates the
+ // existing task manager window.
+ static void Show();
+
+ private:
+ // Initializes the task manager dialog.
void Init();
+ // Sets up the treeview widget.
+ void CreateTaskManagerTreeview();
+
+ // Returns the model data for a given |row| and |col_id|.
+ std::string GetModelText(int row, int col_id);
+
+ // Sets the treeview row data. |row| is an index into the model and |iter|
+ // is the current position in the treeview.
+ void SetRowDataFromModel(int row, GtkTreeIter* iter);
+
+ // Queries the treeview for the selected rows, and kills those processes.
+ void KillSelectedProcesses();
+
// response signal handler that notifies us of dialog responses.
static void OnResponse(GtkDialog* dialog, gint response_id,
TaskManagerGtk* task_manager);
- // Creates the task manager if it doesn't exist; otherwise, it activates the
- // existing task manager window.
- static void Show();
+ // changed signal handler that is sent when the treeview selection changes.
+ static void OnSelectionChanged(GtkTreeSelection* selection,
+ TaskManagerGtk* task_manager);
- private:
// The task manager.
TaskManager* task_manager_;
@@ -41,6 +63,12 @@ class TaskManagerGtk : public TaskManagerModelObserver {
// The treeview that contains the process list.
GtkWidget* treeview_;
+ // The list of processes.
+ GtkListStore* process_list_;
+
+ // The number of processes in |process_list_|.
+ int process_count_;
+
// An open task manager window. There can only be one open at a time. This
// is reset to NULL when the window is closed.
static TaskManagerGtk* instance_;