?? gexmap.cpp
字號:
/* * (c) John Berthels 2005 <jjberthels@gmail.com>. See COPYING for license. */#include <gtkmm.h>#include <gtkmm/window.h>#include "Exmap.hpp"#include "jutil.hpp"#include <boost/shared_ptr.hpp>#include <sstream>#include <iostream>#include <list>namespace Gexmap{ typedef boost::shared_ptr<Gtk::Widget> WidgetPtr; /// Abstract base class for all the list. This will automatically /// add in the columns needed for 'Sizes' after those added by the /// subclass, as well as setting up conveniences such as /// scrollbars, sortable columns etc. class SizeListView : public Gtk::Frame { public: SizeListView(const std::string &frame_name); virtual ~SizeListView(); Gtk::TreeView &listwin(); void update_view(); protected: /// Call this from your ctor, after adding your columns to /// _coluns. void init_store_and_view(); /// Call this from your ctor, after appending your columns to /// the treeview. void init_columns(); /// When creating a new Row, call this to add in the values /// for the Sizes. void add_row_sizes(Gtk::TreeModel::Row &row, Exmap::SizesPtr &sizes); /// Show the list view (hiding the label), and clear the store void show_list(); /// Show the label, with this text (hiding the list) void show_label(const std::string &txt); /// True if we are showing the list, false if the label bool showing_list; Glib::RefPtr<Gtk::ListStore> _store; // We display either the treeview or the errlabel Gtk::TreeView _treeview; Gtk::Label _errlabel; // Hack: reparent the unused child widget to here Gtk::Frame _hidden; /// In the derived class, add columns definitions to this /// record in your ctor. Gtk::TreeModel::ColumnRecord _columns; private: Gtk::TreeModelColumn<float> _size_columns[Exmap::Sizes::NUM_SIZES]; void _make_all_sortable(); static std::string SIZES_PRINTF_FORMAT; Gtk::ScrolledWindow _scrolled_window; }; typedef boost::shared_ptr<SizeListView> SizeListViewPtr; /// Abstract base class for showing processes in a list class ProcList : public SizeListView { public: ProcList(const std::string &frame_name); pid_t currently_selected(); protected: void add_row(pid_t pid, const std::string &cmdline, Exmap::SizesPtr &sizes); Gtk::TreeModelColumn<pid_t> _pid; Gtk::TreeModelColumn<Glib::ustring> _cmdline; }; /// Concrete subclass for showing a top-level list of processes class AllProcList : public ProcList { public: AllProcList(); void set_data(const std::list<Exmap::ProcessPtr> &procs); private: Exmap::SizesPtr calc_totals(const std::list<Exmap::ProcessPtr> &procs); }; /// Concrete subclass for showing the list of process which map a file class PerFileProcList : public ProcList { public: PerFileProcList(); void set_data(const Exmap::FilePtr &file); }; class AllFileList : public SizeListView { public: AllFileList(); void set_data(const std::list<Exmap::FilePtr> &files); std::string currently_selected(); private: Gtk::TreeModelColumn<Glib::ustring> _filename; Gtk::TreeModelColumn<int> _nprocs; }; /// Concrete subclass for showing all files within a process class PerProcFileList : public SizeListView { public: PerProcFileList(); void set_data(const Exmap::ProcessPtr &proc); std::string currently_selected(); private: Gtk::TreeModelColumn<Glib::ustring> _filename; }; /// Concrete subclass for showing the elf sections for a specific /// process and file. class ElfSectionList : public SizeListView { public: ElfSectionList(); Gtk::TreeModelColumn<Glib::ustring> _name; Gtk::TreeModelColumn<off_t> _file_offset; void set_data(const Exmap::ProcessPtr &proc, const Exmap::FilePtr &file); std::string currently_selected(); }; /// Concrete subclass for showing the elf symbols for a specific /// process, file and elf section class ElfSymbolList : public SizeListView { public: ElfSymbolList(); Gtk::TreeModelColumn<Glib::ustring> _name; void set_data(const Exmap::ProcessPtr &proc, const Exmap::FilePtr &file, const Elf::SectionPtr §ion); }; /// Abstract base class for the file and proc tabs class ExmapTab : public Gtk::VPaned { public: ExmapTab(); virtual void set_data(Exmap::SnapshotPtr &snapshot) = 0; protected: Gtk::VPaned _top_half; Gtk::VPaned _bottom_half; // Internal data Exmap::SnapshotPtr _snapshot; // Widgets ElfSectionList _sectionlist; ElfSymbolList _symlist; }; /// The 'Files' Tab class FileTab : public ExmapTab { public: FileTab(); void set_data(Exmap::SnapshotPtr &snapshot); private: // Callbacks void filelist_changed_cb(); void proclist_changed_cb(); void sectionlist_changed_cb(); // Widgets AllFileList _allfilelist; PerFileProcList _proclist; }; /// The 'Processes' Tab class ProcTab : public ExmapTab { public: ProcTab(); void set_data(Exmap::SnapshotPtr &snapshot); private: // Callbacks void proclist_changed_cb(); void filelist_changed_cb(); void sectionlist_changed_cb(); // Widgets AllProcList _allproclist; PerProcFileList _filelist; }; /// Status and button bar class BottomBar : public Gtk::HBox { public: BottomBar(); void set_status(Exmap::SnapshotPtr &snapshot); private: Gtk::Label _plabel; Gtk::Label _flabel; Gtk::Button _quit_button; // Callbacks void quit_button_clicked_cb(); }; /// The main, toplevel window class TopWin : public Gtk::Window { public: TopWin(Exmap::SnapshotPtr &snapshot); static const int WIDTH = 800; static const int HEIGHT = 600; private: // Internal data Exmap::SnapshotPtr _snapshot; // Widgets ProcTab _proctab; FileTab _filetab; Gtk::Notebook _notebook; Gtk::VBox _vbox; BottomBar _bottom_bar; }; };using namespace std;using namespace jutil;using namespace Exmap;using namespace Gexmap;// ------------------------------------------------------------TopWin::TopWin(SnapshotPtr &snapshot) : _snapshot(snapshot){ add(_vbox); _notebook.append_page(_proctab, "Processes"); _notebook.append_page(_filetab, "Files"); _vbox.add(_notebook); _vbox.pack_end(_bottom_bar, false, false); _proctab.set_data(snapshot); _filetab.set_data(snapshot); set_default_size(WIDTH, HEIGHT); _bottom_bar.set_status(_snapshot); show_all();}// ------------------------------------------------------------BottomBar::BottomBar(){ _quit_button.set_label("Quit"); _quit_button.signal_clicked() .connect(sigc::mem_fun(*this, &BottomBar::quit_button_clicked_cb)); add(_plabel); add(_flabel); pack_end(_quit_button, false, false);}void BottomBar::quit_button_clicked_cb(){ Gtk::Main::quit();}void BottomBar::set_status(SnapshotPtr &snapshot){ stringstream sstr; sstr << "Number of procs: " << snapshot->procs().size(); _plabel.set_text(sstr.str()); sstr.str(""); sstr << "Number of files: " << snapshot->files().size(); _flabel.set_text(sstr.str());}// ------------------------------------------------------------SizeListView::SizeListView(const std::string &frame_name) : Gtk::Frame(frame_name), showing_list(true){ _hidden.add(_errlabel); _scrolled_window.add(_treeview); _scrolled_window.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); add(_scrolled_window); _errlabel.show(); _scrolled_window.show_all();}Gtk::TreeView &SizeListView::listwin(){ return _treeview;}SizeListView::~SizeListView(){ }void SizeListView::init_columns(){ Glib::RefPtr<Gtk::TreeModel> model = _treeview.get_model(); int sort_colid = -1; for (int i = 0; i < Exmap::Sizes::NUM_SIZES; ++i) { int colid = _treeview.append_column_numeric(Exmap::Sizes::size_name(i), _size_columns[i], SIZES_PRINTF_FORMAT); // Remember the number of columns first time round the loop if (sort_colid < 0) { sort_colid = colid - 1; } } _make_all_sortable(); _store->set_sort_column_id(sort_colid, Gtk::SORT_DESCENDING);}void SizeListView::_make_all_sortable(){ int ncols = _columns.size(); Gtk::TreeViewColumn *col; for (int i = 0; i < ncols; ++i) { col = _treeview.get_column(i); col->set_sort_column(i); } return;}void SizeListView::init_store_and_view(){ for (int i = 0; i < Exmap::Sizes::NUM_SIZES; ++i) { _columns.add(_size_columns[i]); } _store = Gtk::ListStore::create(_columns); _treeview.set_model(_store);}void SizeListView::add_row_sizes(Gtk::TreeModel::Row &row, Exmap::SizesPtr &sizes){ for (int i = 0; i < Exmap::Sizes::NUM_SIZES; ++i) { row[_size_columns[i]] = sizes->sval(i); }}// We scale to kbytes, so support 4G => 4000000-ish max => 7 leading// digits, plus 2 digits after decimal pt plus the pt = 10 chars in// total.string SizeListView::SIZES_PRINTF_FORMAT("%.2f");void SizeListView::show_label(const string &txt){ _errlabel.set_text(txt); if (!showing_list) { return; } Gtk::Frame tmp; _errlabel.reparent(tmp); _scrolled_window.reparent(_hidden); _errlabel.reparent(*this); showing_list = false;}void SizeListView::show_list(){ _store->clear(); if (showing_list) { return; } Gtk::Frame tmp; _scrolled_window.reparent(tmp); _errlabel.reparent(_hidden); _scrolled_window.reparent(*this); showing_list = true;}// ------------------------------------------------------------ProcList::ProcList(const std::string &frame_name) : SizeListView(frame_name){ _columns.add(_pid); _columns.add(_cmdline); init_store_and_view(); _treeview.append_column("PID", _pid); _treeview.append_column("Cmdline", _cmdline); init_columns();} pid_t ProcList::currently_selected(){ Glib::RefPtr<Gtk::TreeSelection> sel = listwin().get_selection(); Glib::RefPtr<Gtk::TreeModel> model = listwin().get_model(); pid_t pid = 0; // invalid if (sel->count_selected_rows() == 1) { Gtk::TreeModel::iterator iter = sel->get_selected(model); if (iter) { Gtk::TreeModel::Row row = *iter; pid = row.get_value(_pid); } } return pid;}void ProcList::add_row(pid_t pid, const string &cmdline, SizesPtr &sizes){ Gtk::TreeModel::Row row = *(_store->append()); row[_pid] = pid; row[_cmdline] = cmdline; add_row_sizes(row, sizes);}// ------------------------------------------------------------
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -