diff options
author | jhawkins@chromium.org <jhawkins@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-01 16:31:07 +0000 |
---|---|---|
committer | jhawkins@chromium.org <jhawkins@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-01 16:31:07 +0000 |
commit | 48c17f3fd63823010d7af9f5ff9832880eed1fcb (patch) | |
tree | d1b287446ee3d98b3fad6cdbc00c7ac61fc13252 /chrome | |
parent | 011479016795f1dd436f81849a21fd8d6ff65ce3 (diff) | |
download | chromium_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.cc | 289 | ||||
-rw-r--r-- | chrome/browser/gtk/task_manager_gtk.h | 36 |
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_; |