Implemented the animated button using a KAnimWidget.
[kdbg.git] / kdbg / procattach.cpp
blob496b0061b4fbb952f37db24cd31178ff688b08c5
1 // $Id$
3 // Copyright by Johannes Sixt
4 // This file is under GPL, the GNU General Public Licence
6 #include "procattach.h"
7 #include <qlistview.h>
8 #include <kprocess.h>
9 #include <ctype.h>
10 #include <kapp.h>
11 #include <klocale.h> /* i18n */
12 #ifdef HAVE_CONFIG_H
13 #include "config.h"
14 #endif
17 ProcAttachPS::ProcAttachPS(QWidget* parent) :
18 ProcAttachBase(parent),
19 m_pidCol(-1),
20 m_ppidCol(-1)
22 m_ps = new KProcess;
23 connect(m_ps, SIGNAL(receivedStdout(KProcess*, char*, int)),
24 this, SLOT(slotTextReceived(KProcess*, char*, int)));
26 processList->setColumnWidth(0, 300);
27 processList->setColumnWidthMode(0, QListView::Manual);
28 processList->setColumnAlignment(1, Qt::AlignRight);
29 processList->setColumnAlignment(2, Qt::AlignRight);
31 // set the command line
32 static const char* const psCommand[] = {
33 #ifdef PS_COMMAND
34 PS_COMMAND,
35 #else
36 "/bin/false",
37 #endif
40 for (int i = 0; psCommand[i] != 0; i++) {
41 *m_ps << psCommand[i];
44 runPS();
47 ProcAttachPS::~ProcAttachPS()
49 delete m_ps; // kills a running ps
52 void ProcAttachPS::runPS()
54 // clear the parse state from previous runs
55 m_token = "";
56 m_line.clear();
57 m_pidCol = -1;
58 m_ppidCol = -1;
60 m_ps->start(KProcess::NotifyOnExit, KProcess::Stdout);
63 void ProcAttachPS::slotTextReceived(KProcess*, char* buffer, int buflen)
65 const char* end = buffer+buflen;
66 while (buffer < end)
68 // check new line
69 if (*buffer == '\n')
71 // push a tokens onto the line
72 if (!m_token.isEmpty()) {
73 m_line.push_back(QString::fromLatin1(m_token));
74 m_token = "";
76 // and insert the line in the list
77 pushLine();
78 m_line.clear();
79 ++buffer;
81 // blanks: the last column gets the rest of the line, including blanks
82 else if ((m_pidCol < 0 || int(m_line.size()) < processList->columns()-1) &&
83 isspace(*buffer))
85 // push a token onto the line
86 if (!m_token.isEmpty()) {
87 m_line.push_back(QString::fromLatin1(m_token));
88 m_token = "";
90 do {
91 ++buffer;
92 } while (buffer < end && isspace(*buffer));
94 // tokens
95 else
97 const char* start = buffer;
98 do {
99 ++buffer;
100 } while (buffer < end && !isspace(*buffer));
101 // append to the current token
102 m_token += QCString(start, buffer-start+1); // must count the '\0'
107 void ProcAttachPS::pushLine()
109 if (m_line.size() < 3) // we need the PID, PPID, and COMMAND columns
110 return;
112 if (m_pidCol < 0)
114 // create columns if we don't have them yet
115 bool allocate = processList->columns() == 3;
117 // we assume that the last column is the command
118 m_line.pop_back();
120 for (uint i = 0; i < m_line.size(); i++) {
121 // we don't allocate the PID and PPID columns,
122 // but we need to know where in the ps output they are
123 if (m_line[i] == "PID") {
124 m_pidCol = i;
125 } else if (m_line[i] == "PPID") {
126 m_ppidCol = i;
127 } else if (allocate) {
128 processList->addColumn(m_line[i]);
129 // these columns are normally numbers
130 processList->setColumnAlignment(processList->columns()-1,
131 Qt::AlignRight);
135 else
137 // insert a line
138 // find the parent process
139 QListViewItem* parent = 0;
140 if (m_ppidCol >= 0 && m_ppidCol < int(m_line.size())) {
141 parent = processList->findItem(m_line[m_ppidCol], 1);
144 // we assume that the last column is the command
145 QListViewItem* item;
146 if (parent == 0) {
147 item = new QListViewItem(processList, m_line.back());
148 } else {
149 item = new QListViewItem(parent, m_line.back());
151 item->setOpen(true);
152 m_line.pop_back();
153 int k = 3;
154 for (uint i = 0; i < m_line.size(); i++)
156 // display the pid and ppid columns' contents in columns 1 and 2
157 if (int(i) == m_pidCol)
158 item->setText(1, m_line[i]);
159 else if (int(i) == m_ppidCol)
160 item->setText(2, m_line[i]);
161 else
162 item->setText(k++, m_line[i]);
165 if (m_ppidCol >= 0 && m_pidCol >= 0) { // need PID & PPID for this
167 * It could have happened that a process was earlier inserted,
168 * whose parent process is the current process. Such processes
169 * were placed at the root. Here we go through all root items
170 * and check whether we must reparent them.
172 QListViewItem* i = processList->firstChild();
173 while (i != 0)
175 // advance before we reparent the item
176 QListViewItem* it = i;
177 i = i->nextSibling();
178 if (it->text(2) == m_line[m_pidCol]) {
179 processList->takeItem(it);
180 item->insertItem(it);
187 void ProcAttachPS::processSelected(QListViewItem* item)
189 if (item != 0) {
190 pidEdit->setText(item->text(1));
191 processText->setText(item->text(0));
195 void ProcAttachPS::refresh()
197 if (!m_ps->isRunning())
199 processList->clear();
200 runPS();
204 void ProcAttachPS::pidEdited(const QString& text)
206 if (text.isEmpty())
207 return;
209 // get the process and select it
210 QListViewItem* item = processList->findItem(text, 1);
211 if (item == 0) {
212 processList->clearSelection();
213 } else {
214 processList->setSelected(item, true);
215 processList->ensureItemVisible(item);
220 ProcAttach::ProcAttach(QWidget* parent) :
221 QDialog(parent, "procattach", true),
222 m_label(this, "label"),
223 m_processId(this, "procid"),
224 m_buttonOK(this, "ok"),
225 m_buttonCancel(this, "cancel"),
226 m_layout(this, 8),
227 m_buttons(4)
229 QString title = kapp->caption();
230 title += i18n(": Attach to process");
231 setCaption(title);
233 m_label.setMinimumSize(330, 24);
234 m_label.setText(i18n("Specify the process number to attach to:"));
236 m_processId.setMinimumSize(330, 24);
237 m_processId.setMaxLength(100);
238 m_processId.setFrame(true);
240 m_buttonOK.setMinimumSize(100, 30);
241 connect(&m_buttonOK, SIGNAL(clicked()), SLOT(accept()));
242 m_buttonOK.setText(i18n("OK"));
243 m_buttonOK.setDefault(true);
245 m_buttonCancel.setMinimumSize(100, 30);
246 connect(&m_buttonCancel, SIGNAL(clicked()), SLOT(reject()));
247 m_buttonCancel.setText(i18n("Cancel"));
249 m_layout.addWidget(&m_label);
250 m_layout.addWidget(&m_processId);
251 m_layout.addLayout(&m_buttons);
252 m_layout.addStretch(10);
253 m_buttons.addStretch(10);
254 m_buttons.addWidget(&m_buttonOK);
255 m_buttons.addSpacing(40);
256 m_buttons.addWidget(&m_buttonCancel);
257 m_buttons.addStretch(10);
259 m_layout.activate();
261 m_processId.setFocus();
262 resize(350, 120);
265 ProcAttach::~ProcAttach()