2 * Copyright Johannes Sixt
3 * This file is licensed under the GNU General Public License Version 2.
4 * See the file COPYING in the toplevel directory of the source directory.
7 #include "procattach.h"
12 #include <kiconloader.h>
13 #include <klocale.h> /* i18n */
17 ProcAttachPS::ProcAttachPS(QWidget
* parent
) :
23 on_processList_selectionChanged(); //update OK button disabled state.
26 connect(m_ps
, SIGNAL(readyReadStandardOutput()),
27 this, SLOT(slotTextReceived()));
28 connect(m_ps
, SIGNAL(finished(int,QProcess::ExitStatus
)),
29 this, SLOT(slotPSDone()));
31 processList
->setColumnWidth(0, 300);
32 processList
->setColumnWidthMode(0, Q3ListView::Manual
);
33 processList
->setColumnAlignment(1, Qt::AlignRight
);
34 processList
->setColumnAlignment(2, Qt::AlignRight
);
39 ProcAttachPS::~ProcAttachPS()
41 delete m_ps
; // kills a running ps
44 void ProcAttachPS::runPS()
46 // clear the parse state from previous runs
52 // set the command line
53 char* const psCommand
[] = {
62 for (int i
= 1; psCommand
[i
] != 0; i
++) {
63 args
.push_back(psCommand
[i
]);
66 m_ps
->start(psCommand
[0], args
);
69 void ProcAttachPS::slotTextReceived()
71 QByteArray data
= m_ps
->readAllStandardOutput();
72 char* buffer
= data
.data();
73 char* end
= buffer
+ data
.size();
80 // push a tokens onto the line
81 if (!m_token
.isEmpty()) {
82 m_line
.push_back(QString::fromLatin1(m_token
));
85 // and insert the line in the list
90 // blanks: the last column gets the rest of the line, including blanks
91 else if ((m_pidCol
< 0 || int(m_line
.size()) < processList
->columns()-1) &&
94 // push a token onto the line
95 if (!m_token
.isEmpty()) {
96 m_line
.push_back(QString::fromLatin1(m_token
));
101 } while (buffer
< end
&& isspace(*buffer
));
106 const char* start
= buffer
;
109 } while (buffer
< end
&& !isspace(*buffer
));
110 // append to the current token
111 m_token
+= Q3CString(start
, buffer
-start
+1); // must count the '\0'
116 void ProcAttachPS::pushLine()
118 if (m_line
.size() < 3) // we need the PID, PPID, and COMMAND columns
123 // create columns if we don't have them yet
124 bool allocate
= processList
->columns() == 3;
126 // we assume that the last column is the command
129 for (int i
= 0; i
< m_line
.size(); i
++) {
130 // we don't allocate the PID and PPID columns,
131 // but we need to know where in the ps output they are
132 if (m_line
[i
] == "PID") {
134 } else if (m_line
[i
] == "PPID") {
136 } else if (allocate
) {
137 processList
->addColumn(m_line
[i
]);
138 // these columns are normally numbers
139 processList
->setColumnAlignment(processList
->columns()-1,
147 // find the parent process
148 Q3ListViewItem
* parent
= 0;
149 if (m_ppidCol
>= 0 && m_ppidCol
< int(m_line
.size())) {
150 parent
= processList
->findItem(m_line
[m_ppidCol
], 1);
153 // we assume that the last column is the command
154 Q3ListViewItem
* item
;
156 item
= new Q3ListViewItem(processList
, m_line
.back());
158 item
= new Q3ListViewItem(parent
, m_line
.back());
163 for (int i
= 0; i
< m_line
.size(); i
++)
165 // display the pid and ppid columns' contents in columns 1 and 2
166 if (int(i
) == m_pidCol
)
167 item
->setText(1, m_line
[i
]);
168 else if (int(i
) == m_ppidCol
)
169 item
->setText(2, m_line
[i
]);
171 item
->setText(k
++, m_line
[i
]);
174 if (m_ppidCol
>= 0 && m_pidCol
>= 0) { // need PID & PPID for this
176 * It could have happened that a process was earlier inserted,
177 * whose parent process is the current process. Such processes
178 * were placed at the root. Here we go through all root items
179 * and check whether we must reparent them.
181 Q3ListViewItem
* i
= processList
->firstChild();
184 // advance before we reparent the item
185 Q3ListViewItem
* it
= i
;
186 i
= i
->nextSibling();
187 if (it
->text(2) == m_line
[m_pidCol
]) {
188 processList
->takeItem(it
);
189 item
->insertItem(it
);
196 void ProcAttachPS::slotPSDone()
198 on_filterEdit_textChanged(filterEdit
->text());
201 QString
ProcAttachPS::text() const
203 Q3ListViewItem
* item
= processList
->selectedItem();
208 return item
->text(1);
211 void ProcAttachPS::on_buttonRefresh_clicked()
213 if (m_ps
->state() == QProcess::NotRunning
)
215 processList
->clear();
216 dialogButtons
->button(QDialogButtonBox::Ok
)->setEnabled(false); // selection was cleared
221 void ProcAttachPS::on_filterEdit_textChanged(const QString
& text
)
223 for (Q3ListViewItem
* i
= processList
->firstChild(); i
; i
= i
->nextSibling())
224 setVisibility(i
, text
);
228 * Sets the visibility of \a i and
229 * returns whether it was made visible.
231 bool ProcAttachPS::setVisibility(Q3ListViewItem
* i
, const QString
& text
)
234 bool visible
= false;
235 for (Q3ListViewItem
* j
= i
->firstChild(); j
; j
= j
->nextSibling())
237 if (setVisibility(j
, text
))
240 // look for text in the process name and in the PID
241 visible
= visible
|| text
.isEmpty() ||
242 i
->text(0).find(text
, 0, false) >= 0 ||
243 i
->text(1).find(text
) >= 0;
246 i
->setVisible(false);
248 // disable the OK button if the selected item becomes invisible
250 dialogButtons
->button(QDialogButtonBox::Ok
)->setEnabled(visible
);
255 void ProcAttachPS::on_processList_selectionChanged()
257 dialogButtons
->button(QDialogButtonBox::Ok
)->setEnabled(processList
->selectedItem() != 0);
261 ProcAttach::ProcAttach(QWidget
* parent
) :
262 QDialog(parent
, "procattach", true),
263 m_label(this, "label"),
264 m_processId(this, "procid"),
265 m_buttonOK(this, "ok"),
266 m_buttonCancel(this, "cancel"),
270 QString title
= KGlobal::caption();
271 title
+= i18n(": Attach to process");
274 m_label
.setMinimumSize(330, 24);
275 m_label
.setText(i18n("Specify the process number to attach to:"));
277 m_processId
.setMinimumSize(330, 24);
278 m_processId
.setMaxLength(100);
279 m_processId
.setFrame(true);
281 m_buttonOK
.setMinimumSize(100, 30);
282 connect(&m_buttonOK
, SIGNAL(clicked()), SLOT(accept()));
283 m_buttonOK
.setText(i18n("OK"));
284 m_buttonOK
.setDefault(true);
286 m_buttonCancel
.setMinimumSize(100, 30);
287 connect(&m_buttonCancel
, SIGNAL(clicked()), SLOT(reject()));
288 m_buttonCancel
.setText(i18n("Cancel"));
290 m_layout
.addWidget(&m_label
);
291 m_layout
.addWidget(&m_processId
);
292 m_layout
.addLayout(&m_buttons
);
293 m_layout
.addStretch(10);
294 m_buttons
.addStretch(10);
295 m_buttons
.addWidget(&m_buttonOK
);
296 m_buttons
.addSpacing(40);
297 m_buttons
.addWidget(&m_buttonCancel
);
298 m_buttons
.addStretch(10);
302 m_processId
.setFocus();
306 ProcAttach::~ProcAttach()
311 #include "procattach.moc"