3 // Copyright by Johannes Sixt
4 // This file is under GPL, the GNU General Public Licence
6 #include "procattach.h"
8 #include <qtoolbutton.h>
13 #include <kiconloader.h>
14 #include <klocale.h> /* i18n */
20 ProcAttachPS::ProcAttachPS(QWidget
* parent
) :
21 ProcAttachBase(parent
),
26 connect(m_ps
, SIGNAL(receivedStdout(KProcess
*, char*, int)),
27 this, SLOT(slotTextReceived(KProcess
*, char*, int)));
28 connect(m_ps
, SIGNAL(processExited(KProcess
*)),
29 this, SLOT(slotPSDone()));
31 QIconSet icon
= SmallIconSet("clear_left");
32 filterClear
->setIconSet(icon
);
34 processList
->setColumnWidth(0, 300);
35 processList
->setColumnWidthMode(0, QListView::Manual
);
36 processList
->setColumnAlignment(1, Qt::AlignRight
);
37 processList
->setColumnAlignment(2, Qt::AlignRight
);
39 // set the command line
40 static const char* const psCommand
[] = {
48 for (int i
= 0; psCommand
[i
] != 0; i
++) {
49 *m_ps
<< psCommand
[i
];
55 ProcAttachPS::~ProcAttachPS()
57 delete m_ps
; // kills a running ps
60 void ProcAttachPS::runPS()
62 // clear the parse state from previous runs
68 m_ps
->start(KProcess::NotifyOnExit
, KProcess::Stdout
);
71 void ProcAttachPS::slotTextReceived(KProcess
*, char* buffer
, int buflen
)
73 const char* end
= buffer
+buflen
;
79 // push a tokens onto the line
80 if (!m_token
.isEmpty()) {
81 m_line
.push_back(QString::fromLatin1(m_token
));
84 // and insert the line in the list
89 // blanks: the last column gets the rest of the line, including blanks
90 else if ((m_pidCol
< 0 || int(m_line
.size()) < processList
->columns()-1) &&
93 // push a token onto the line
94 if (!m_token
.isEmpty()) {
95 m_line
.push_back(QString::fromLatin1(m_token
));
100 } while (buffer
< end
&& isspace(*buffer
));
105 const char* start
= buffer
;
108 } while (buffer
< end
&& !isspace(*buffer
));
109 // append to the current token
110 m_token
+= QCString(start
, buffer
-start
+1); // must count the '\0'
115 void ProcAttachPS::pushLine()
117 if (m_line
.size() < 3) // we need the PID, PPID, and COMMAND columns
122 // create columns if we don't have them yet
123 bool allocate
= processList
->columns() == 3;
125 // we assume that the last column is the command
128 for (uint i
= 0; i
< m_line
.size(); i
++) {
129 // we don't allocate the PID and PPID columns,
130 // but we need to know where in the ps output they are
131 if (m_line
[i
] == "PID") {
133 } else if (m_line
[i
] == "PPID") {
135 } else if (allocate
) {
136 processList
->addColumn(m_line
[i
]);
137 // these columns are normally numbers
138 processList
->setColumnAlignment(processList
->columns()-1,
146 // find the parent process
147 QListViewItem
* parent
= 0;
148 if (m_ppidCol
>= 0 && m_ppidCol
< int(m_line
.size())) {
149 parent
= processList
->findItem(m_line
[m_ppidCol
], 1);
152 // we assume that the last column is the command
155 item
= new QListViewItem(processList
, m_line
.back());
157 item
= new QListViewItem(parent
, m_line
.back());
162 for (uint i
= 0; i
< m_line
.size(); i
++)
164 // display the pid and ppid columns' contents in columns 1 and 2
165 if (int(i
) == m_pidCol
)
166 item
->setText(1, m_line
[i
]);
167 else if (int(i
) == m_ppidCol
)
168 item
->setText(2, m_line
[i
]);
170 item
->setText(k
++, m_line
[i
]);
173 if (m_ppidCol
>= 0 && m_pidCol
>= 0) { // need PID & PPID for this
175 * It could have happened that a process was earlier inserted,
176 * whose parent process is the current process. Such processes
177 * were placed at the root. Here we go through all root items
178 * and check whether we must reparent them.
180 QListViewItem
* i
= processList
->firstChild();
183 // advance before we reparent the item
184 QListViewItem
* it
= i
;
185 i
= i
->nextSibling();
186 if (it
->text(2) == m_line
[m_pidCol
]) {
187 processList
->takeItem(it
);
188 item
->insertItem(it
);
195 void ProcAttachPS::slotPSDone()
197 filterEdited(filterEdit
->text());
200 QString
ProcAttachPS::text() const
202 QListViewItem
* item
= processList
->selectedItem();
207 return item
->text(1);
210 void ProcAttachPS::refresh()
212 if (!m_ps
->isRunning())
214 processList
->clear();
219 void ProcAttachPS::filterEdited(const QString
& text
)
221 QListViewItem
* i
= processList
->firstChild();
222 setVisibility(i
, text
);
226 * Sets the visibility of \a i and
227 * returns whether it was made visible.
229 bool ProcAttachPS::setVisibility(QListViewItem
* i
, const QString
& text
)
231 bool visible
= false;
232 for (QListViewItem
* j
= i
->firstChild(); j
; j
= j
->nextSibling())
234 if (setVisibility(j
, text
))
237 // look for text in the process name and in the PID
238 visible
= visible
|| text
.isEmpty() ||
239 i
->text(0).find(text
, 0, false) >= 0 ||
240 i
->text(1).find(text
) >= 0;
242 i
->setVisible(visible
);
248 ProcAttach::ProcAttach(QWidget
* parent
) :
249 QDialog(parent
, "procattach", true),
250 m_label(this, "label"),
251 m_processId(this, "procid"),
252 m_buttonOK(this, "ok"),
253 m_buttonCancel(this, "cancel"),
257 QString title
= kapp
->caption();
258 title
+= i18n(": Attach to process");
261 m_label
.setMinimumSize(330, 24);
262 m_label
.setText(i18n("Specify the process number to attach to:"));
264 m_processId
.setMinimumSize(330, 24);
265 m_processId
.setMaxLength(100);
266 m_processId
.setFrame(true);
268 m_buttonOK
.setMinimumSize(100, 30);
269 connect(&m_buttonOK
, SIGNAL(clicked()), SLOT(accept()));
270 m_buttonOK
.setText(i18n("OK"));
271 m_buttonOK
.setDefault(true);
273 m_buttonCancel
.setMinimumSize(100, 30);
274 connect(&m_buttonCancel
, SIGNAL(clicked()), SLOT(reject()));
275 m_buttonCancel
.setText(i18n("Cancel"));
277 m_layout
.addWidget(&m_label
);
278 m_layout
.addWidget(&m_processId
);
279 m_layout
.addLayout(&m_buttons
);
280 m_layout
.addStretch(10);
281 m_buttons
.addStretch(10);
282 m_buttons
.addWidget(&m_buttonOK
);
283 m_buttons
.addSpacing(40);
284 m_buttons
.addWidget(&m_buttonCancel
);
285 m_buttons
.addStretch(10);
289 m_processId
.setFocus();
293 ProcAttach::~ProcAttach()