OSDN Git Service

It's 2011 now.
[qt-creator-jp/qt-creator-jp.git] / src / plugins / debugger / debuggerdialogs.cpp
1 /**************************************************************************
2 **
3 ** This file is part of Qt Creator
4 **
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
6 **
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
8 **
9 ** No Commercial Usage
10 **
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 **
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Nokia gives you certain additional
26 ** rights.  These rights are described in the Nokia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
31 **
32 **************************************************************************/
33
34 #include "debuggerdialogs.h"
35
36 #include "debuggerconstants.h"
37 #include "cdb/cdbengine.h"
38
39 #include "ui_attachcoredialog.h"
40 #include "ui_attachexternaldialog.h"
41 #include "ui_attachtcfdialog.h"
42 #include "ui_startexternaldialog.h"
43 #include "ui_startremotedialog.h"
44 #include "ui_startremoteenginedialog.h"
45
46 #ifdef Q_OS_WIN
47 #  include "shared/dbgwinutils.h"
48 #endif
49
50 #include <coreplugin/icore.h>
51 #include <utils/synchronousprocess.h>
52 #include <utils/historycompleter.h>
53 #include <utils/qtcassert.h>
54
55 #include <QtCore/QDebug>
56 #include <QtCore/QProcess>
57 #include <QtCore/QRegExp>
58 #include <QtCore/QDir>
59 #include <QtCore/QFile>
60 #include <QtCore/QCoreApplication>
61 #include <QtGui/QStandardItemModel>
62 #include <QtGui/QHeaderView>
63 #include <QtGui/QFileDialog>
64 #include <QtGui/QPushButton>
65 #include <QtGui/QProxyModel>
66 #include <QtGui/QSortFilterProxyModel>
67 #include <QtGui/QMessageBox>
68 #include <QtGui/QGroupBox>
69
70 using namespace Utils;
71
72 namespace Debugger {
73 namespace Internal {
74
75 bool operator<(const ProcData &p1, const ProcData &p2)
76 {
77     return p1.name < p2.name;
78 }
79
80 // A filterable process list model
81 class ProcessListFilterModel : public QSortFilterProxyModel
82 {
83 public:
84     explicit ProcessListFilterModel(QObject *parent);
85     QString processIdAt(const QModelIndex &index) const;
86     QString executableForPid(const QString& pid) const;
87
88     void populate(QList<ProcData> processes, const QString &excludePid);
89
90 private:
91     enum { ProcessImageRole = Qt::UserRole, ProcessNameRole };
92
93     bool lessThan(const QModelIndex &left, const QModelIndex &right) const;
94
95     QStandardItemModel *m_model;
96 };
97
98 ProcessListFilterModel::ProcessListFilterModel(QObject *parent)
99   : QSortFilterProxyModel(parent),
100     m_model(new QStandardItemModel(this))
101 {
102     QStringList columns;
103     columns << AttachExternalDialog::tr("Process ID")
104             << AttachExternalDialog::tr("Name")
105             << AttachExternalDialog::tr("State");
106     m_model->setHorizontalHeaderLabels(columns);
107     setSourceModel(m_model);
108     setFilterCaseSensitivity(Qt::CaseInsensitive);
109     setFilterKeyColumn(1);
110 }
111
112 bool ProcessListFilterModel::lessThan(const QModelIndex &left,
113     const QModelIndex &right) const
114 {
115     const QString l = sourceModel()->data(left).toString();
116     const QString r = sourceModel()->data(right).toString();
117     if (left.column() == 0)
118         return l.toInt() < r.toInt();
119     return l < r;
120 }
121
122 QString ProcessListFilterModel::processIdAt(const QModelIndex &index) const
123 {
124     if (index.isValid()) {
125         const QModelIndex index0 = mapToSource(index);
126         QModelIndex siblingIndex = index0.sibling(index0.row(), 0);
127         if (const QStandardItem *item = m_model->itemFromIndex(siblingIndex))
128             return item->text();
129     }
130     return QString();
131 }
132
133 QString ProcessListFilterModel::executableForPid(const QString &pid) const
134 {
135     const int rowCount = m_model->rowCount();
136     for (int r = 0; r < rowCount; r++) {
137         const QStandardItem *item = m_model->item(r, 0);
138         if (item->text() == pid) {
139             QString name = item->data(ProcessImageRole).toString();
140             if (name.isEmpty())
141                 name = item->data(ProcessNameRole).toString();
142             return name;
143         }
144     }
145     return QString();
146 }
147
148 void ProcessListFilterModel::populate
149     (QList<ProcData> processes, const QString &excludePid)
150 {
151     qStableSort(processes);
152
153     if (const int rowCount = m_model->rowCount())
154         m_model->removeRows(0, rowCount);
155
156     QStandardItem *root  = m_model->invisibleRootItem();
157     foreach (const ProcData &proc, processes) {
158         QList<QStandardItem *> row;
159         row.append(new QStandardItem(proc.ppid));
160         QString name = proc.image.isEmpty() ? proc.name : proc.image;
161         row.back()->setData(name, ProcessImageRole);
162         row.append(new QStandardItem(proc.name));
163         row.back()->setToolTip(proc.image);
164         row.append(new QStandardItem(proc.state));
165
166         if (proc.ppid == excludePid)
167             foreach (QStandardItem *item, row)
168                 item->setEnabled(false);
169         root->appendRow(row);
170     }
171 }
172
173
174 ///////////////////////////////////////////////////////////////////////
175 //
176 // AttachCoreDialog
177 //
178 ///////////////////////////////////////////////////////////////////////
179
180 AttachCoreDialog::AttachCoreDialog(QWidget *parent)
181   : QDialog(parent), m_ui(new Ui::AttachCoreDialog)
182 {
183     m_ui->setupUi(this);
184
185     m_ui->execFileName->setExpectedKind(PathChooser::File);
186     m_ui->execFileName->setPromptDialogTitle(tr("Select Executable"));
187
188     m_ui->coreFileName->setExpectedKind(PathChooser::File);
189     m_ui->coreFileName->setPromptDialogTitle(tr("Select Core File"));
190
191     m_ui->buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
192
193     connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
194     connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
195 }
196
197 AttachCoreDialog::~AttachCoreDialog()
198 {
199     delete m_ui;
200 }
201
202 QString AttachCoreDialog::executableFile() const
203 {
204     return m_ui->execFileName->path();
205 }
206
207 void AttachCoreDialog::setExecutableFile(const QString &fileName)
208 {
209     m_ui->execFileName->setPath(fileName);
210 }
211
212 QString AttachCoreDialog::coreFile() const
213 {
214     return m_ui->coreFileName->path();
215 }
216
217 void AttachCoreDialog::setCoreFile(const QString &fileName)
218 {
219     m_ui->coreFileName->setPath(fileName);
220 }
221
222
223 ///////////////////////////////////////////////////////////////////////
224 //
225 // Process model helpers
226 //
227 ///////////////////////////////////////////////////////////////////////
228
229 #ifndef Q_OS_WIN
230
231 static bool isUnixProcessId(const QString &procname)
232 {
233     for (int i = 0; i != procname.size(); ++i)
234         if (!procname.at(i).isDigit())
235             return false;
236     return true;
237 }
238
239
240 // Determine UNIX processes by running ps
241 static QList<ProcData> unixProcessListPS()
242 {
243 #ifdef Q_OS_MAC
244     static const char formatC[] = "pid state command";
245 #else
246     static const char formatC[] = "pid,state,cmd";
247 #endif
248     QList<ProcData> rc;
249     QProcess psProcess;
250     QStringList args;
251     args << QLatin1String("-e") << QLatin1String("-o") << QLatin1String(formatC);
252     psProcess.start(QLatin1String("ps"), args);
253     if (!psProcess.waitForStarted())
254         return rc;
255     QByteArray output;
256     if (!SynchronousProcess::readDataFromProcess(psProcess, 30000, &output, 0, false))
257         return rc;
258     // Split "457 S+   /Users/foo.app"
259     const QStringList lines = QString::fromLocal8Bit(output).split(QLatin1Char('\n'));
260     const int lineCount = lines.size();
261     const QChar blank = QLatin1Char(' ');
262     for (int l = 1; l < lineCount; l++) { // Skip header
263         const QString line = lines.at(l).simplified();
264         const int pidSep = line.indexOf(blank);
265         const int cmdSep = pidSep != -1 ? line.indexOf(blank, pidSep + 1) : -1;
266         if (cmdSep > 0) {
267             ProcData procData;
268             procData.ppid = line.left(pidSep);
269             procData.state = line.mid(pidSep + 1, cmdSep - pidSep - 1);
270             procData.name = line.mid(cmdSep + 1);
271             rc.push_back(procData);
272         }
273     }
274     return rc;
275 }
276
277 // Determine UNIX processes by reading "/proc". Default to ps if
278 // it does not exist
279 static QList<ProcData> unixProcessList()
280 {
281     const QDir procDir(QLatin1String("/proc/"));
282     if (!procDir.exists())
283         return unixProcessListPS();
284     QList<ProcData> rc;
285     const QStringList procIds = procDir.entryList();
286     if (procIds.isEmpty())
287         return rc;
288     foreach (const QString &procId, procIds) {
289         if (!isUnixProcessId(procId))
290             continue;
291         QString filename = QLatin1String("/proc/");
292         filename += procId;
293         filename += QLatin1String("/stat");
294         QFile file(filename);
295         if (!file.open(QIODevice::ReadOnly))
296             continue;           // process may have exited
297
298         const QStringList data = QString::fromLocal8Bit(file.readAll()).split(' ');
299         ProcData proc;
300         proc.ppid = procId;
301         proc.name = data.at(1);
302         if (proc.name.startsWith(QLatin1Char('(')) && proc.name.endsWith(QLatin1Char(')'))) {
303             proc.name.truncate(proc.name.size() - 1);
304             proc.name.remove(0, 1);
305         }
306         proc.state = data.at(2);
307         // PPID is element 3
308         rc.push_back(proc);
309     }
310     return rc;
311 }
312 #endif // Q_OS_WIN
313
314 static QList<ProcData> processList()
315 {
316 #ifdef Q_OS_WIN
317     return winProcessList();
318 #else
319     return unixProcessList();
320 #endif
321 }
322
323
324 ///////////////////////////////////////////////////////////////////////
325 //
326 // AttachExternalDialog
327 //
328 ///////////////////////////////////////////////////////////////////////
329
330 AttachExternalDialog::AttachExternalDialog(QWidget *parent)
331   : QDialog(parent),
332     m_selfPid(QString::number(QCoreApplication::applicationPid())),
333     m_ui(new Ui::AttachExternalDialog),
334     m_model(new ProcessListFilterModel(this))
335 {
336     m_ui->setupUi(this);
337     okButton()->setDefault(true);
338     okButton()->setEnabled(false);
339
340     m_ui->procView->setModel(m_model);
341     m_ui->procView->setSortingEnabled(true);
342     m_ui->procView->sortByColumn(1, Qt::AscendingOrder);
343
344     connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
345     connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
346     QPushButton *refreshButton = new QPushButton(tr("Refresh"));
347     connect(refreshButton, SIGNAL(clicked()), this, SLOT(rebuildProcessList()));
348     m_ui->buttonBox->addButton(refreshButton, QDialogButtonBox::ActionRole);
349     m_ui->filterWidget->setFocus(Qt::TabFocusReason);
350
351     m_ui->procView->setAlternatingRowColors(true);
352     m_ui->procView->setRootIsDecorated(false);
353     m_ui->procView->setUniformRowHeights(true);
354
355     // Do not use activated, will be single click in Oxygen
356     connect(m_ui->procView, SIGNAL(doubleClicked(QModelIndex)),
357         this, SLOT(procSelected(QModelIndex)));
358     connect(m_ui->procView, SIGNAL(clicked(QModelIndex)),
359         this, SLOT(procClicked(QModelIndex)));
360     connect(m_ui->pidLineEdit, SIGNAL(textChanged(QString)),
361             this, SLOT(pidChanged(QString)));
362     connect(m_ui->filterWidget, SIGNAL(filterChanged(QString)),
363             this, SLOT(setFilterString(QString)));
364
365
366     setMinimumHeight(500);
367     rebuildProcessList();
368 }
369
370 AttachExternalDialog::~AttachExternalDialog()
371 {
372     delete m_ui;
373 }
374
375 void AttachExternalDialog::setFilterString(const QString &filter)
376 {
377     m_model->setFilterFixedString(filter);
378     // Activate the line edit if there's a unique filtered process.
379     QString processId;
380     if (m_model->rowCount(QModelIndex()) == 1)
381         processId = m_model->processIdAt(m_model->index(0, 0, QModelIndex()));
382     m_ui->pidLineEdit->setText(processId);
383     pidChanged(processId);
384 }
385
386 QPushButton *AttachExternalDialog::okButton() const
387 {
388     return m_ui->buttonBox->button(QDialogButtonBox::Ok);
389 }
390
391 void AttachExternalDialog::rebuildProcessList()
392 {
393     m_model->populate(processList(), m_selfPid);
394     m_ui->procView->expandAll();
395     m_ui->procView->resizeColumnToContents(0);
396     m_ui->procView->resizeColumnToContents(1);
397 }
398
399 void AttachExternalDialog::procSelected(const QModelIndex &proxyIndex)
400 {
401     const QString processId = m_model->processIdAt(proxyIndex);
402     if (!processId.isEmpty()) {
403         m_ui->pidLineEdit->setText(processId);
404         if (okButton()->isEnabled())
405             okButton()->animateClick();
406     }
407 }
408
409 void AttachExternalDialog::procClicked(const QModelIndex &proxyIndex)
410 {
411     const QString processId = m_model->processIdAt(proxyIndex);
412     if (!processId.isEmpty())
413         m_ui->pidLineEdit->setText(processId);
414 }
415
416 QString AttachExternalDialog::attachPIDText() const
417 {
418     return m_ui->pidLineEdit->text().trimmed();
419 }
420
421 qint64 AttachExternalDialog::attachPID() const
422 {
423     return attachPIDText().toLongLong();
424 }
425
426 QString AttachExternalDialog::executable() const
427 {
428     // Search pid in model in case the user typed in the PID.
429     return m_model->executableForPid(attachPIDText());
430 }
431
432 void AttachExternalDialog::pidChanged(const QString &pid)
433 {
434     bool enabled = !pid.isEmpty() && pid != QLatin1String("0") && pid != m_selfPid;
435     okButton()->setEnabled(enabled);
436 }
437
438 void AttachExternalDialog::accept()
439 {
440 #ifdef Q_OS_WIN
441     const qint64 pid = attachPID();
442     if (pid && isWinProcessBeingDebugged(pid)) {
443         QMessageBox::warning(this, tr("Process Already Under Debugger Control"),
444                              tr("The process %1 is already under the control of a debugger.\n"
445                                 "Qt Creator cannot attach to it.").arg(pid));
446         return;
447     }
448 #endif
449     QDialog::accept();
450 }
451
452
453 ///////////////////////////////////////////////////////////////////////
454 //
455 // AttachTcfDialog
456 //
457 ///////////////////////////////////////////////////////////////////////
458
459 AttachTcfDialog::AttachTcfDialog(QWidget *parent)
460   : QDialog(parent),
461     m_ui(new Ui::AttachTcfDialog)
462 {
463     m_ui->setupUi(this);
464     m_ui->buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
465     m_ui->serverStartScript->setExpectedKind(PathChooser::File);
466     m_ui->serverStartScript->setPromptDialogTitle(tr("Select Executable"));
467
468     connect(m_ui->useServerStartScriptCheckBox, SIGNAL(toggled(bool)), 
469         this, SLOT(updateState()));
470     
471     connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
472     connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
473
474     updateState();
475 }
476
477 AttachTcfDialog::~AttachTcfDialog()
478 {
479     delete m_ui;
480 }
481
482 void AttachTcfDialog::setRemoteChannel(const QString &channel)
483 {
484     m_ui->channelLineEdit->setText(channel);
485 }
486
487 QString AttachTcfDialog::remoteChannel() const
488 {
489     return m_ui->channelLineEdit->text();
490 }
491
492 void AttachTcfDialog::setRemoteArchitectures(const QStringList &list)
493 {
494     m_ui->architectureComboBox->clear();
495     if (!list.isEmpty()) {
496         m_ui->architectureComboBox->insertItems(0, list);
497         m_ui->architectureComboBox->setCurrentIndex(0);
498     }
499 }
500
501 void AttachTcfDialog::setRemoteArchitecture(const QString &arch)
502 {
503     int index = m_ui->architectureComboBox->findText(arch);
504     if (index != -1)
505         m_ui->architectureComboBox->setCurrentIndex(index);
506 }
507
508 QString AttachTcfDialog::remoteArchitecture() const
509 {
510     int index = m_ui->architectureComboBox->currentIndex();
511     return m_ui->architectureComboBox->itemText(index);
512 }
513
514 void AttachTcfDialog::setServerStartScript(const QString &scriptName)
515 {
516     m_ui->serverStartScript->setPath(scriptName);
517 }
518
519 QString AttachTcfDialog::serverStartScript() const
520 {
521     return m_ui->serverStartScript->path();
522 }
523
524 void AttachTcfDialog::setUseServerStartScript(bool on)
525 {
526     m_ui->useServerStartScriptCheckBox->setChecked(on);
527 }
528
529 bool AttachTcfDialog::useServerStartScript() const
530 {
531     return m_ui->useServerStartScriptCheckBox->isChecked();
532 }
533
534 void AttachTcfDialog::updateState()
535 {
536     bool enabled = m_ui->useServerStartScriptCheckBox->isChecked();
537     m_ui->serverStartScriptLabel->setEnabled(enabled);
538     m_ui->serverStartScript->setEnabled(enabled);
539 }
540
541
542 ///////////////////////////////////////////////////////////////////////
543 //
544 // StartExternalDialog
545 //
546 ///////////////////////////////////////////////////////////////////////
547
548 StartExternalDialog::StartExternalDialog(QWidget *parent)
549   : QDialog(parent), m_ui(new Ui::StartExternalDialog)
550 {
551     m_ui->setupUi(this);
552     m_ui->execFile->setExpectedKind(PathChooser::File);
553     m_ui->execFile->setPromptDialogTitle(tr("Select Executable"));
554     m_ui->execFile->lineEdit()->setCompleter(
555         new HistoryCompleter(m_ui->execFile->lineEdit()));
556     m_ui->buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
557     m_ui->workingDirectory->setExpectedKind(PathChooser::Directory);
558     m_ui->workingDirectory->setPromptDialogTitle(tr("Select Working Directory"));
559     m_ui->workingDirectory->lineEdit()->setCompleter(
560         new HistoryCompleter(m_ui->workingDirectory->lineEdit()));
561
562     //execLabel->setHidden(false);
563     //execEdit->setHidden(false);
564     //browseButton->setHidden(false);
565
566     m_ui->execLabel->setText(tr("Executable:"));
567     m_ui->argsLabel->setText(tr("Arguments:"));
568     m_ui->argsEdit->setCompleter(new HistoryCompleter(m_ui->argsEdit));
569
570     connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
571     connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
572 }
573
574 StartExternalDialog::~StartExternalDialog()
575 {
576     delete m_ui;
577 }
578
579 void StartExternalDialog::setExecutableFile(const QString &str)
580 {
581     m_ui->execFile->setPath(str);
582 }
583
584 QString StartExternalDialog::executableFile() const
585 {
586     return m_ui->execFile->path();
587 }
588
589 void StartExternalDialog::setWorkingDirectory(const QString &str)
590 {
591     m_ui->workingDirectory->setPath(str);
592 }
593
594 QString StartExternalDialog::workingDirectory() const
595 {
596     return m_ui->workingDirectory->path();
597 }
598
599 void StartExternalDialog::setExecutableArguments(const QString &str)
600 {
601     m_ui->argsEdit->setText(str);
602 }
603
604 QString StartExternalDialog::executableArguments() const
605 {
606     return m_ui->argsEdit->text();
607 }
608
609 bool StartExternalDialog::breakAtMain() const
610 {
611     return m_ui->checkBoxBreakAtMain->isChecked();
612 }
613
614 ///////////////////////////////////////////////////////////////////////
615 //
616 // StartRemoteDialog
617 //
618 ///////////////////////////////////////////////////////////////////////
619
620 StartRemoteDialog::StartRemoteDialog(QWidget *parent)
621   : QDialog(parent),
622     m_ui(new Ui::StartRemoteDialog)
623 {
624     m_ui->setupUi(this);
625     m_ui->buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
626     m_ui->debuggerPathChooser->setExpectedKind(PathChooser::File);
627     m_ui->debuggerPathChooser->setPromptDialogTitle(tr("Select Debugger"));
628     m_ui->executablePathChooser->setExpectedKind(PathChooser::File);
629     m_ui->executablePathChooser->setPromptDialogTitle(tr("Select Executable"));
630     m_ui->sysrootPathChooser->setPromptDialogTitle(tr("Select Sysroot"));
631     m_ui->serverStartScript->setExpectedKind(PathChooser::File);
632     m_ui->serverStartScript->setPromptDialogTitle(tr("Select Start Script"));
633
634     connect(m_ui->useServerStartScriptCheckBox, SIGNAL(toggled(bool)),
635         this, SLOT(updateState()));
636
637     connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
638     connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
639
640     updateState();
641 }
642
643 StartRemoteDialog::~StartRemoteDialog()
644 {
645     delete m_ui;
646 }
647
648 void StartRemoteDialog::setRemoteChannel(const QString &channel)
649 {
650     m_ui->channelLineEdit->setText(channel);
651 }
652
653 QString StartRemoteDialog::remoteChannel() const
654 {
655     return m_ui->channelLineEdit->text();
656 }
657
658 void StartRemoteDialog::setLocalExecutable(const QString &executable)
659 {
660     m_ui->executablePathChooser->setPath(executable);
661 }
662
663 QString StartRemoteDialog::localExecutable() const
664 {
665     return m_ui->executablePathChooser->path();
666 }
667
668 void StartRemoteDialog::setDebugger(const QString &debugger)
669 {
670     m_ui->debuggerPathChooser->setPath(debugger);
671 }
672
673 QString StartRemoteDialog::debugger() const
674 {
675     return m_ui->debuggerPathChooser->path();
676 }
677
678 void StartRemoteDialog::setRemoteArchitectures(const QStringList &list)
679 {
680     m_ui->architectureComboBox->clear();
681     if (!list.isEmpty()) {
682         m_ui->architectureComboBox->insertItems(0, list);
683         m_ui->architectureComboBox->setCurrentIndex(0);
684     }
685 }
686
687 void StartRemoteDialog::setRemoteArchitecture(const QString &arch)
688 {
689     int index = m_ui->architectureComboBox->findText(arch);
690     if (index != -1)
691         m_ui->architectureComboBox->setCurrentIndex(index);
692 }
693
694 QString StartRemoteDialog::remoteArchitecture() const
695 {
696     return m_ui->architectureComboBox->currentText();
697 }
698
699 QString StartRemoteDialog::gnuTarget() const
700 {
701     return m_ui->gnuTargetComboBox->currentText();
702 }
703
704 void StartRemoteDialog::setGnuTargets(const QStringList &gnuTargets)
705 {
706     m_ui->gnuTargetComboBox->clear();
707     if (!gnuTargets.isEmpty()) {
708         m_ui->gnuTargetComboBox->insertItems(0, gnuTargets);
709         m_ui->gnuTargetComboBox->setCurrentIndex(0);
710     }
711 }
712
713 void StartRemoteDialog::setGnuTarget(const QString &gnuTarget)
714 {
715     const int index = m_ui->gnuTargetComboBox->findText(gnuTarget);
716     if (index != -1)
717         m_ui->gnuTargetComboBox->setCurrentIndex(index);
718 }
719
720 void StartRemoteDialog::setServerStartScript(const QString &scriptName)
721 {
722     m_ui->serverStartScript->setPath(scriptName);
723 }
724
725 QString StartRemoteDialog::serverStartScript() const
726 {
727     return m_ui->serverStartScript->path();
728 }
729
730 void StartRemoteDialog::setUseServerStartScript(bool on)
731 {
732     m_ui->useServerStartScriptCheckBox->setChecked(on);
733 }
734
735 bool StartRemoteDialog::useServerStartScript() const
736 {
737     return m_ui->useServerStartScriptCheckBox->isChecked();
738 }
739
740 void StartRemoteDialog::setSysRoot(const QString &sysroot)
741 {
742     m_ui->sysrootPathChooser->setPath(sysroot);
743 }
744
745 QString StartRemoteDialog::sysRoot() const
746 {
747     return m_ui->sysrootPathChooser->path();
748 }
749
750 void StartRemoteDialog::updateState()
751 {
752     bool enabled = m_ui->useServerStartScriptCheckBox->isChecked();
753     m_ui->serverStartScriptLabel->setEnabled(enabled);
754     m_ui->serverStartScript->setEnabled(enabled);
755 }
756
757 // --------- StartRemoteCdbDialog
758 static inline QString cdbRemoteHelp()
759 {
760     const char *cdbConnectionSyntax =
761             "Server:Port<br>"
762             "tcp:server=Server,port=Port[,password=Password][,ipversion=6]\n"
763             "tcp:clicon=Server,port=Port[,password=Password][,ipversion=6]\n"
764             "npipe:server=Server,pipe=PipeName[,password=Password]\n"
765             "com:port=COMPort,baud=BaudRate,channel=COMChannel[,password=Password]\n"
766             "spipe:proto=Protocol,{certuser=Cert|machuser=Cert},server=Server,pipe=PipeName[,password=Password]\n"
767             "ssl:proto=Protocol,{certuser=Cert|machuser=Cert},server=Server,port=Socket[,password=Password]\n"
768             "ssl:proto=Protocol,{certuser=Cert|machuser=Cert},clicon=Server,port=Socket[,password=Password]";
769
770     const QString ext32 = QDir::toNativeSeparators(CdbEngine::extensionLibraryName(false));
771     const QString ext64 = QDir::toNativeSeparators(CdbEngine::extensionLibraryName(true));
772     return  StartRemoteCdbDialog::tr(
773                 "<html><body><p>The remote CDB needs to load the matching Qt Creator CDB extension "
774                 "(<code>%1</code> or <code>%2</code>, respectively).</p><p>Copy it onto the remote machine and set the "
775                 "environment variable <code>%3</code> to point to its folder.</p><p>"
776                 "Launch the remote CDB as <code>%4 &lt;executable&gt;</code> "
777                 " to use TCP/IP as communication protocol.</p><p>Enter the connection parameters as:</p>"
778                 "<pre>%5</pre></body></html>").
779             arg(ext32, ext64, QLatin1String("_NT_DEBUGGER_EXTENSION_PATH"),
780                 QLatin1String("cdb.exe -server tcp:port=1234"),
781                 QLatin1String(cdbConnectionSyntax));
782 }
783
784 StartRemoteCdbDialog::StartRemoteCdbDialog(QWidget *parent) :
785     QDialog(parent), m_okButton(0), m_lineEdit(new QLineEdit)
786 {
787     setWindowTitle(tr("Start a CDB Remote Session"));
788     setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
789
790     QGroupBox *groupBox = new QGroupBox;
791     QFormLayout *formLayout = new QFormLayout;
792     QLabel *helpLabel = new QLabel(cdbRemoteHelp());
793     helpLabel->setWordWrap(true);
794     helpLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
795     formLayout->addRow(helpLabel);
796     QLabel *label = new QLabel(tr("&Connection:"));
797     label->setBuddy(m_lineEdit);
798     m_lineEdit->setMinimumWidth(400);
799     connect(m_lineEdit, SIGNAL(textChanged(QString)), this, SLOT(textChanged(QString)));
800     formLayout->addRow(label, m_lineEdit);
801     groupBox->setLayout(formLayout);
802
803     QVBoxLayout *vLayout = new QVBoxLayout;
804     vLayout->addWidget(groupBox);
805     QDialogButtonBox *box = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel);
806     vLayout->addWidget(box);
807     m_okButton = box->button(QDialogButtonBox::Ok);
808     connect(m_lineEdit, SIGNAL(returnPressed()), m_okButton, SLOT(animateClick()));
809     m_okButton->setEnabled(false);
810     connect(box, SIGNAL(accepted()), this, SLOT(accept()));
811     connect(box, SIGNAL(rejected()), this, SLOT(reject()));
812
813     setLayout(vLayout);
814 }
815
816 void StartRemoteCdbDialog::accept()
817 {
818     if (!m_lineEdit->text().isEmpty())
819         QDialog::accept();
820 }
821
822 StartRemoteCdbDialog::~StartRemoteCdbDialog()
823 {
824 }
825
826 void StartRemoteCdbDialog::textChanged(const QString &t)
827 {
828     m_okButton->setEnabled(!t.isEmpty());
829 }
830
831 QString StartRemoteCdbDialog::connection() const
832 {
833     const QString rc = m_lineEdit->text();
834     // Transform an IP:POrt ('localhost:1234') specification into full spec
835     QRegExp ipRegexp(QLatin1String("([\\w\\.\\-_]+):([0-9]{1,4})"));
836     QTC_ASSERT(ipRegexp.isValid(), return QString());
837     if (ipRegexp.exactMatch(rc))
838         return QString::fromAscii("tcp:server=%1,port=%2").arg(ipRegexp.cap(1), ipRegexp.cap(2));
839     return rc;
840 }
841
842 void StartRemoteCdbDialog::setConnection(const QString &c)
843 {
844     m_lineEdit->setText(c);
845     m_okButton->setEnabled(!c.isEmpty());
846 }
847
848 AddressDialog::AddressDialog(QWidget *parent) :
849         QDialog(parent),
850         m_lineEdit(new QLineEdit),
851         m_box(new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel))
852 {
853     setWindowTitle(tr("Select Start Address"));
854     setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
855     QHBoxLayout *hLayout = new QHBoxLayout;
856     hLayout->addWidget(new QLabel(tr("Enter an address: ")));
857     hLayout->addWidget(m_lineEdit);
858     QVBoxLayout *vLayout = new QVBoxLayout;
859     vLayout->addLayout(hLayout);
860     vLayout->addWidget(m_box);
861     setLayout(vLayout);
862
863     connect(m_box, SIGNAL(accepted()), this, SLOT(accept()));
864     connect(m_box, SIGNAL(rejected()), this, SLOT(reject()));
865     connect(m_lineEdit, SIGNAL(returnPressed()), this, SLOT(accept()));
866     connect(m_lineEdit, SIGNAL(textChanged(QString)), this, SLOT(textChanged()));
867
868     setOkButtonEnabled(false);
869 }
870
871 void AddressDialog::setOkButtonEnabled(bool v)
872 {
873     m_box->button(QDialogButtonBox::Ok)->setEnabled(v);
874 }
875
876 bool AddressDialog::isOkButtonEnabled() const
877 {
878     return m_box->button(QDialogButtonBox::Ok)->isEnabled();
879 }
880
881 quint64 AddressDialog::address() const
882 {
883     return m_lineEdit->text().toULongLong(0, 16);
884 }
885
886 void AddressDialog::accept()
887 {
888     if (isOkButtonEnabled())
889         QDialog::accept();
890 }
891
892 void AddressDialog::textChanged()
893 {
894     setOkButtonEnabled(isValid());
895 }
896
897 bool AddressDialog::isValid() const
898 {
899     const QString text = m_lineEdit->text();
900     bool ok = false;
901     text.toULongLong(&ok, 16);
902     return ok;
903 }
904
905 ///////////////////////////////////////////////////////////////////////
906 //
907 // StartRemoteEngineDialog
908 //
909 ///////////////////////////////////////////////////////////////////////
910
911 StartRemoteEngineDialog::StartRemoteEngineDialog(QWidget *parent) :
912     QDialog(parent) ,
913     m_ui(new Ui::StartRemoteEngineDialog)
914 {
915      m_ui->setupUi(this);
916      m_ui->host->setCompleter(new HistoryCompleter(m_ui->host));
917      m_ui->username->setCompleter(new HistoryCompleter(m_ui->username));
918      m_ui->enginepath->setCompleter(new HistoryCompleter(m_ui->enginepath));
919      m_ui->inferiorpath->setCompleter(new HistoryCompleter(m_ui->inferiorpath));
920      connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
921      connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
922 }
923
924 StartRemoteEngineDialog::~StartRemoteEngineDialog()
925 {
926 }
927
928 QString StartRemoteEngineDialog::host() const
929 {
930     return m_ui->host->text();
931 }
932
933 QString StartRemoteEngineDialog::username() const
934 {
935     return m_ui->username->text();
936 }
937
938 QString StartRemoteEngineDialog::password() const
939 {
940     return m_ui->password->text();
941 }
942
943 QString StartRemoteEngineDialog::inferiorPath() const
944 {
945     return m_ui->inferiorpath->text();
946 }
947
948 QString StartRemoteEngineDialog::enginePath() const
949 {
950     return m_ui->enginepath->text();
951 }
952
953
954 } // namespace Internal
955 } // namespace Debugger