OSDN Git Service

b6553f2f740f43c93ca1351ba63f114f498214d6
[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_startexternaldialog.h"
42 #include "ui_startremotedialog.h"
43 #include "ui_startremoteenginedialog.h"
44
45 #ifdef Q_OS_WIN
46 #  include "shared/dbgwinutils.h"
47 #endif
48
49 #include <coreplugin/icore.h>
50 #include <projectexplorer/abi.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     setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
184     m_ui->setupUi(this);
185     m_ui->toolchainComboBox->init(false);
186
187     m_ui->execFileName->setExpectedKind(PathChooser::File);
188     m_ui->execFileName->setPromptDialogTitle(tr("Select Executable"));
189
190     m_ui->coreFileName->setExpectedKind(PathChooser::File);
191     m_ui->coreFileName->setPromptDialogTitle(tr("Select Core File"));
192
193     m_ui->buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
194
195     connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
196     connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
197     connect(m_ui->coreFileName, SIGNAL(changed(QString)), this, SLOT(changed()));
198     connect(m_ui->execFileName, SIGNAL(changed(QString)), this, SLOT(changed()));
199     changed();
200 }
201
202 AttachCoreDialog::~AttachCoreDialog()
203 {
204     delete m_ui;
205 }
206
207 QString AttachCoreDialog::executableFile() const
208 {
209     return m_ui->execFileName->path();
210 }
211
212 void AttachCoreDialog::setExecutableFile(const QString &fileName)
213 {
214     m_ui->execFileName->setPath(fileName);
215     changed();
216 }
217
218 QString AttachCoreDialog::coreFile() const
219 {
220     return m_ui->coreFileName->path();
221 }
222
223 void AttachCoreDialog::setCoreFile(const QString &fileName)
224 {
225     m_ui->coreFileName->setPath(fileName);
226     changed();
227 }
228
229 ProjectExplorer::Abi AttachCoreDialog::abi() const
230 {
231     return m_ui->toolchainComboBox->abi();
232 }
233
234 void AttachCoreDialog::setAbiIndex(int i)
235 {
236     if (i >= 0 && i < m_ui->toolchainComboBox->count())
237         m_ui->toolchainComboBox->setCurrentIndex(i);
238 }
239
240 int AttachCoreDialog::abiIndex() const
241 {
242     return m_ui->toolchainComboBox->currentIndex();
243 }
244
245 QString AttachCoreDialog::debuggerCommand()
246 {
247     return m_ui->toolchainComboBox->debuggerCommand();
248 }
249
250 bool AttachCoreDialog::isValid() const
251 {
252     return m_ui->toolchainComboBox->currentIndex() >= 0 &&
253            !coreFile().isEmpty();
254 }
255
256 void AttachCoreDialog::changed()
257 {
258     m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(isValid());
259 }
260
261 ///////////////////////////////////////////////////////////////////////
262 //
263 // Process model helpers
264 //
265 ///////////////////////////////////////////////////////////////////////
266
267 #ifndef Q_OS_WIN
268
269 static bool isUnixProcessId(const QString &procname)
270 {
271     for (int i = 0; i != procname.size(); ++i)
272         if (!procname.at(i).isDigit())
273             return false;
274     return true;
275 }
276
277
278 // Determine UNIX processes by running ps
279 static QList<ProcData> unixProcessListPS()
280 {
281 #ifdef Q_OS_MAC
282     static const char formatC[] = "pid state command";
283 #else
284     static const char formatC[] = "pid,state,cmd";
285 #endif
286     QList<ProcData> rc;
287     QProcess psProcess;
288     QStringList args;
289     args << QLatin1String("-e") << QLatin1String("-o") << QLatin1String(formatC);
290     psProcess.start(QLatin1String("ps"), args);
291     if (!psProcess.waitForStarted())
292         return rc;
293     QByteArray output;
294     if (!SynchronousProcess::readDataFromProcess(psProcess, 30000, &output, 0, false))
295         return rc;
296     // Split "457 S+   /Users/foo.app"
297     const QStringList lines = QString::fromLocal8Bit(output).split(QLatin1Char('\n'));
298     const int lineCount = lines.size();
299     const QChar blank = QLatin1Char(' ');
300     for (int l = 1; l < lineCount; l++) { // Skip header
301         const QString line = lines.at(l).simplified();
302         const int pidSep = line.indexOf(blank);
303         const int cmdSep = pidSep != -1 ? line.indexOf(blank, pidSep + 1) : -1;
304         if (cmdSep > 0) {
305             ProcData procData;
306             procData.ppid = line.left(pidSep);
307             procData.state = line.mid(pidSep + 1, cmdSep - pidSep - 1);
308             procData.name = line.mid(cmdSep + 1);
309             rc.push_back(procData);
310         }
311     }
312     return rc;
313 }
314
315 // Determine UNIX processes by reading "/proc". Default to ps if
316 // it does not exist
317 static QList<ProcData> unixProcessList()
318 {
319     const QDir procDir(QLatin1String("/proc/"));
320     if (!procDir.exists())
321         return unixProcessListPS();
322     QList<ProcData> rc;
323     const QStringList procIds = procDir.entryList();
324     if (procIds.isEmpty())
325         return rc;
326     foreach (const QString &procId, procIds) {
327         if (!isUnixProcessId(procId))
328             continue;
329         QString filename = QLatin1String("/proc/");
330         filename += procId;
331         filename += QLatin1String("/stat");
332         QFile file(filename);
333         if (!file.open(QIODevice::ReadOnly))
334             continue;           // process may have exited
335
336         const QStringList data = QString::fromLocal8Bit(file.readAll()).split(' ');
337         ProcData proc;
338         proc.ppid = procId;
339         proc.name = data.at(1);
340         if (proc.name.startsWith(QLatin1Char('(')) && proc.name.endsWith(QLatin1Char(')'))) {
341             proc.name.truncate(proc.name.size() - 1);
342             proc.name.remove(0, 1);
343         }
344         proc.state = data.at(2);
345         // PPID is element 3
346         rc.push_back(proc);
347     }
348     return rc;
349 }
350 #endif // Q_OS_WIN
351
352 static QList<ProcData> processList()
353 {
354 #ifdef Q_OS_WIN
355     return winProcessList();
356 #else
357     return unixProcessList();
358 #endif
359 }
360
361
362 ///////////////////////////////////////////////////////////////////////
363 //
364 // AttachExternalDialog
365 //
366 ///////////////////////////////////////////////////////////////////////
367
368 AttachExternalDialog::AttachExternalDialog(QWidget *parent)
369   : QDialog(parent),
370     m_selfPid(QString::number(QCoreApplication::applicationPid())),
371     m_ui(new Ui::AttachExternalDialog),
372     m_model(new ProcessListFilterModel(this))
373 {
374     setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
375     m_ui->setupUi(this);
376     m_ui->toolchainComboBox->init(true);
377     okButton()->setDefault(true);
378     okButton()->setEnabled(false);
379
380     m_ui->procView->setModel(m_model);
381     m_ui->procView->setSortingEnabled(true);
382     m_ui->procView->sortByColumn(1, Qt::AscendingOrder);
383
384     connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
385     connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
386     QPushButton *refreshButton = new QPushButton(tr("Refresh"));
387     connect(refreshButton, SIGNAL(clicked()), this, SLOT(rebuildProcessList()));
388     m_ui->buttonBox->addButton(refreshButton, QDialogButtonBox::ActionRole);
389     m_ui->filterWidget->setFocus(Qt::TabFocusReason);
390
391     m_ui->procView->setAlternatingRowColors(true);
392     m_ui->procView->setRootIsDecorated(false);
393     m_ui->procView->setUniformRowHeights(true);
394
395     // Do not use activated, will be single click in Oxygen
396     connect(m_ui->procView, SIGNAL(doubleClicked(QModelIndex)),
397         this, SLOT(procSelected(QModelIndex)));
398     connect(m_ui->procView, SIGNAL(clicked(QModelIndex)),
399         this, SLOT(procClicked(QModelIndex)));
400     connect(m_ui->pidLineEdit, SIGNAL(textChanged(QString)),
401             this, SLOT(pidChanged(QString)));
402     connect(m_ui->filterWidget, SIGNAL(filterChanged(QString)),
403             this, SLOT(setFilterString(QString)));
404
405
406     setMinimumHeight(500);
407     rebuildProcessList();
408 }
409
410 AttachExternalDialog::~AttachExternalDialog()
411 {
412     delete m_ui;
413 }
414
415 void AttachExternalDialog::setFilterString(const QString &filter)
416 {
417     m_model->setFilterFixedString(filter);
418     // Activate the line edit if there's a unique filtered process.
419     QString processId;
420     if (m_model->rowCount(QModelIndex()) == 1)
421         processId = m_model->processIdAt(m_model->index(0, 0, QModelIndex()));
422     m_ui->pidLineEdit->setText(processId);
423     pidChanged(processId);
424 }
425
426 QPushButton *AttachExternalDialog::okButton() const
427 {
428     return m_ui->buttonBox->button(QDialogButtonBox::Ok);
429 }
430
431 void AttachExternalDialog::rebuildProcessList()
432 {
433     m_model->populate(processList(), m_selfPid);
434     m_ui->procView->expandAll();
435     m_ui->procView->resizeColumnToContents(0);
436     m_ui->procView->resizeColumnToContents(1);
437 }
438
439 void AttachExternalDialog::procSelected(const QModelIndex &proxyIndex)
440 {
441     const QString processId = m_model->processIdAt(proxyIndex);
442     if (!processId.isEmpty()) {
443         m_ui->pidLineEdit->setText(processId);
444         if (okButton()->isEnabled())
445             okButton()->animateClick();
446     }
447 }
448
449 void AttachExternalDialog::procClicked(const QModelIndex &proxyIndex)
450 {
451     const QString processId = m_model->processIdAt(proxyIndex);
452     if (!processId.isEmpty())
453         m_ui->pidLineEdit->setText(processId);
454 }
455
456 QString AttachExternalDialog::attachPIDText() const
457 {
458     return m_ui->pidLineEdit->text().trimmed();
459 }
460
461 qint64 AttachExternalDialog::attachPID() const
462 {
463     return attachPIDText().toLongLong();
464 }
465
466 QString AttachExternalDialog::executable() const
467 {
468     // Search pid in model in case the user typed in the PID.
469     return m_model->executableForPid(attachPIDText());
470 }
471
472 ProjectExplorer::Abi AttachExternalDialog::abi() const
473 {
474     return m_ui->toolchainComboBox->abi();
475 }
476
477 void AttachExternalDialog::setAbiIndex(int i)
478 {
479     if (i >= 0 && i < m_ui->toolchainComboBox->count())
480         m_ui->toolchainComboBox->setCurrentIndex(i);
481 }
482
483 int AttachExternalDialog::abiIndex() const
484 {
485     return m_ui->toolchainComboBox->currentIndex();
486 }
487
488 QString AttachExternalDialog::debuggerCommand()
489 {
490     return m_ui->toolchainComboBox->debuggerCommand();
491 }
492
493 void AttachExternalDialog::pidChanged(const QString &pid)
494 {
495     const bool enabled = !pid.isEmpty() && pid != QLatin1String("0") && pid != m_selfPid
496             && m_ui->toolchainComboBox->currentIndex() >= 0;
497     okButton()->setEnabled(enabled);
498 }
499
500 void AttachExternalDialog::accept()
501 {
502 #ifdef Q_OS_WIN
503     const qint64 pid = attachPID();
504     if (pid && isWinProcessBeingDebugged(pid)) {
505         QMessageBox::warning(this, tr("Process Already Under Debugger Control"),
506                              tr("The process %1 is already under the control of a debugger.\n"
507                                 "Qt Creator cannot attach to it.").arg(pid));
508         return;
509     }
510 #endif
511     QDialog::accept();
512 }
513
514
515 ///////////////////////////////////////////////////////////////////////
516 //
517 // StartExternalDialog
518 //
519 ///////////////////////////////////////////////////////////////////////
520
521 StartExternalDialog::StartExternalDialog(QWidget *parent)
522   : QDialog(parent), m_ui(new Ui::StartExternalDialog)
523 {
524     setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
525     m_ui->setupUi(this);
526     m_ui->toolChainComboBox->init(true);
527     m_ui->execFile->setExpectedKind(PathChooser::File);
528     m_ui->execFile->setPromptDialogTitle(tr("Select Executable"));
529     m_ui->execFile->lineEdit()->setCompleter(
530         new HistoryCompleter(m_ui->execFile->lineEdit()));
531     connect(m_ui->execFile, SIGNAL(changed(QString)), this, SLOT(changed()));
532     m_ui->buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
533     m_ui->workingDirectory->setExpectedKind(PathChooser::ExistingDirectory);
534     m_ui->workingDirectory->setPromptDialogTitle(tr("Select Working Directory"));
535     m_ui->workingDirectory->lineEdit()->setCompleter(
536         new HistoryCompleter(m_ui->workingDirectory->lineEdit()));
537
538     m_ui->argsEdit->setCompleter(new HistoryCompleter(m_ui->argsEdit));
539
540     connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
541     connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
542     changed();
543 }
544
545 StartExternalDialog::~StartExternalDialog()
546 {
547     delete m_ui;
548 }
549
550 void StartExternalDialog::setExecutableFile(const QString &str)
551 {
552     m_ui->execFile->setPath(str);
553     changed();
554 }
555
556 QString StartExternalDialog::executableFile() const
557 {
558     return m_ui->execFile->path();
559 }
560
561 void StartExternalDialog::setWorkingDirectory(const QString &str)
562 {
563     m_ui->workingDirectory->setPath(str);
564 }
565
566 QString StartExternalDialog::workingDirectory() const
567 {
568     return m_ui->workingDirectory->path();
569 }
570
571 void StartExternalDialog::setExecutableArguments(const QString &str)
572 {
573     m_ui->argsEdit->setText(str);
574 }
575
576 QString StartExternalDialog::executableArguments() const
577 {
578     return m_ui->argsEdit->text();
579 }
580
581 bool StartExternalDialog::breakAtMain() const
582 {
583     return m_ui->checkBoxBreakAtMain->isChecked();
584 }
585
586 ProjectExplorer::Abi StartExternalDialog::abi() const
587 {
588     return m_ui->toolChainComboBox->abi();
589 }
590
591 void StartExternalDialog::setAbiIndex(int i)
592 {
593     if (i >= 0 && i < m_ui->toolChainComboBox->count())
594         m_ui->toolChainComboBox->setCurrentIndex(i);
595 }
596
597 int StartExternalDialog::abiIndex() const
598 {
599     return m_ui->toolChainComboBox->currentIndex();
600 }
601
602 QString StartExternalDialog::debuggerCommand()
603 {
604     return m_ui->toolChainComboBox->debuggerCommand();
605 }
606
607 bool StartExternalDialog::isValid() const
608 {
609     return m_ui->toolChainComboBox->currentIndex() >= 0
610            && !executableFile().isEmpty();
611 }
612
613 void StartExternalDialog::changed()
614 {
615     m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(isValid());
616 }
617
618 ///////////////////////////////////////////////////////////////////////
619 //
620 // StartRemoteDialog
621 //
622 ///////////////////////////////////////////////////////////////////////
623
624 StartRemoteDialog::StartRemoteDialog(QWidget *parent)
625   : QDialog(parent),
626     m_ui(new Ui::StartRemoteDialog)
627 {
628     setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
629     m_ui->setupUi(this);
630     m_ui->buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
631     m_ui->debuggerPathChooser->setExpectedKind(PathChooser::File);
632     m_ui->debuggerPathChooser->setPromptDialogTitle(tr("Select Debugger"));
633     m_ui->executablePathChooser->setExpectedKind(PathChooser::File);
634     m_ui->executablePathChooser->setPromptDialogTitle(tr("Select Executable"));
635     m_ui->sysrootPathChooser->setPromptDialogTitle(tr("Select Sysroot"));
636     m_ui->serverStartScript->setExpectedKind(PathChooser::File);
637     m_ui->serverStartScript->setPromptDialogTitle(tr("Select Start Script"));
638
639     connect(m_ui->useServerStartScriptCheckBox, SIGNAL(toggled(bool)),
640         this, SLOT(updateState()));
641
642     connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
643     connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
644
645     updateState();
646 }
647
648 StartRemoteDialog::~StartRemoteDialog()
649 {
650     delete m_ui;
651 }
652
653 void StartRemoteDialog::setRemoteChannel(const QString &channel)
654 {
655     m_ui->channelLineEdit->setText(channel);
656 }
657
658 QString StartRemoteDialog::remoteChannel() const
659 {
660     return m_ui->channelLineEdit->text();
661 }
662
663 void StartRemoteDialog::setLocalExecutable(const QString &executable)
664 {
665     m_ui->executablePathChooser->setPath(executable);
666 }
667
668 QString StartRemoteDialog::localExecutable() const
669 {
670     return m_ui->executablePathChooser->path();
671 }
672
673 void StartRemoteDialog::setDebugger(const QString &debugger)
674 {
675     m_ui->debuggerPathChooser->setPath(debugger);
676 }
677
678 QString StartRemoteDialog::debugger() const
679 {
680     return m_ui->debuggerPathChooser->path();
681 }
682
683 void StartRemoteDialog::setRemoteArchitectures(const QStringList &list)
684 {
685     m_ui->architectureComboBox->clear();
686     if (!list.isEmpty()) {
687         m_ui->architectureComboBox->insertItems(0, list);
688         m_ui->architectureComboBox->setCurrentIndex(0);
689     }
690 }
691
692 void StartRemoteDialog::setRemoteArchitecture(const QString &arch)
693 {
694     int index = m_ui->architectureComboBox->findText(arch);
695     if (index != -1)
696         m_ui->architectureComboBox->setCurrentIndex(index);
697 }
698
699 QString StartRemoteDialog::remoteArchitecture() const
700 {
701     return m_ui->architectureComboBox->currentText();
702 }
703
704 QString StartRemoteDialog::gnuTarget() const
705 {
706     return m_ui->gnuTargetComboBox->currentText();
707 }
708
709 void StartRemoteDialog::setGnuTargets(const QStringList &gnuTargets)
710 {
711     m_ui->gnuTargetComboBox->clear();
712     if (!gnuTargets.isEmpty()) {
713         m_ui->gnuTargetComboBox->insertItems(0, gnuTargets);
714         m_ui->gnuTargetComboBox->setCurrentIndex(0);
715     }
716 }
717
718 void StartRemoteDialog::setGnuTarget(const QString &gnuTarget)
719 {
720     const int index = m_ui->gnuTargetComboBox->findText(gnuTarget);
721     if (index != -1)
722         m_ui->gnuTargetComboBox->setCurrentIndex(index);
723 }
724
725 void StartRemoteDialog::setServerStartScript(const QString &scriptName)
726 {
727     m_ui->serverStartScript->setPath(scriptName);
728 }
729
730 QString StartRemoteDialog::serverStartScript() const
731 {
732     return m_ui->serverStartScript->path();
733 }
734
735 void StartRemoteDialog::setUseServerStartScript(bool on)
736 {
737     m_ui->useServerStartScriptCheckBox->setChecked(on);
738 }
739
740 bool StartRemoteDialog::useServerStartScript() const
741 {
742     return m_ui->useServerStartScriptCheckBox->isChecked();
743 }
744
745 void StartRemoteDialog::setSysRoot(const QString &sysroot)
746 {
747     m_ui->sysrootPathChooser->setPath(sysroot);
748 }
749
750 QString StartRemoteDialog::sysRoot() const
751 {
752     return m_ui->sysrootPathChooser->path();
753 }
754
755 void StartRemoteDialog::updateState()
756 {
757     bool enabled = m_ui->useServerStartScriptCheckBox->isChecked();
758     m_ui->serverStartScriptLabel->setEnabled(enabled);
759     m_ui->serverStartScript->setEnabled(enabled);
760 }
761
762 // --------- StartRemoteCdbDialog
763 static inline QString cdbRemoteHelp()
764 {
765     const char *cdbConnectionSyntax =
766             "Server:Port<br>"
767             "tcp:server=Server,port=Port[,password=Password][,ipversion=6]\n"
768             "tcp:clicon=Server,port=Port[,password=Password][,ipversion=6]\n"
769             "npipe:server=Server,pipe=PipeName[,password=Password]\n"
770             "com:port=COMPort,baud=BaudRate,channel=COMChannel[,password=Password]\n"
771             "spipe:proto=Protocol,{certuser=Cert|machuser=Cert},server=Server,pipe=PipeName[,password=Password]\n"
772             "ssl:proto=Protocol,{certuser=Cert|machuser=Cert},server=Server,port=Socket[,password=Password]\n"
773             "ssl:proto=Protocol,{certuser=Cert|machuser=Cert},clicon=Server,port=Socket[,password=Password]";
774
775     const QString ext32 = QDir::toNativeSeparators(CdbEngine::extensionLibraryName(false));
776     const QString ext64 = QDir::toNativeSeparators(CdbEngine::extensionLibraryName(true));
777     return  StartRemoteCdbDialog::tr(
778                 "<html><body><p>The remote CDB needs to load the matching Qt Creator CDB extension "
779                 "(<code>%1</code> or <code>%2</code>, respectively).</p><p>Copy it onto the remote machine and set the "
780                 "environment variable <code>%3</code> to point to its folder.</p><p>"
781                 "Launch the remote CDB as <code>%4 &lt;executable&gt;</code> "
782                 " to use TCP/IP as communication protocol.</p><p>Enter the connection parameters as:</p>"
783                 "<pre>%5</pre></body></html>").
784             arg(ext32, ext64, QLatin1String("_NT_DEBUGGER_EXTENSION_PATH"),
785                 QLatin1String("cdb.exe -server tcp:port=1234"),
786                 QLatin1String(cdbConnectionSyntax));
787 }
788
789 StartRemoteCdbDialog::StartRemoteCdbDialog(QWidget *parent) :
790     QDialog(parent), m_okButton(0), m_lineEdit(new QLineEdit)
791 {
792     setWindowTitle(tr("Start a CDB Remote Session"));
793     setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
794
795     QGroupBox *groupBox = new QGroupBox;
796     QFormLayout *formLayout = new QFormLayout;
797     QLabel *helpLabel = new QLabel(cdbRemoteHelp());
798     helpLabel->setWordWrap(true);
799     helpLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
800     formLayout->addRow(helpLabel);
801     QLabel *label = new QLabel(tr("&Connection:"));
802     label->setBuddy(m_lineEdit);
803     m_lineEdit->setMinimumWidth(400);
804     connect(m_lineEdit, SIGNAL(textChanged(QString)), this, SLOT(textChanged(QString)));
805     formLayout->addRow(label, m_lineEdit);
806     groupBox->setLayout(formLayout);
807
808     QVBoxLayout *vLayout = new QVBoxLayout;
809     vLayout->addWidget(groupBox);
810     QDialogButtonBox *box = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel);
811     vLayout->addWidget(box);
812     m_okButton = box->button(QDialogButtonBox::Ok);
813     connect(m_lineEdit, SIGNAL(returnPressed()), m_okButton, SLOT(animateClick()));
814     m_okButton->setEnabled(false);
815     connect(box, SIGNAL(accepted()), this, SLOT(accept()));
816     connect(box, SIGNAL(rejected()), this, SLOT(reject()));
817
818     setLayout(vLayout);
819 }
820
821 void StartRemoteCdbDialog::accept()
822 {
823     if (!m_lineEdit->text().isEmpty())
824         QDialog::accept();
825 }
826
827 StartRemoteCdbDialog::~StartRemoteCdbDialog()
828 {
829 }
830
831 void StartRemoteCdbDialog::textChanged(const QString &t)
832 {
833     m_okButton->setEnabled(!t.isEmpty());
834 }
835
836 QString StartRemoteCdbDialog::connection() const
837 {
838     const QString rc = m_lineEdit->text();
839     // Transform an IP:POrt ('localhost:1234') specification into full spec
840     QRegExp ipRegexp(QLatin1String("([\\w\\.\\-_]+):([0-9]{1,4})"));
841     QTC_ASSERT(ipRegexp.isValid(), return QString());
842     if (ipRegexp.exactMatch(rc))
843         return QString::fromAscii("tcp:server=%1,port=%2").arg(ipRegexp.cap(1), ipRegexp.cap(2));
844     return rc;
845 }
846
847 void StartRemoteCdbDialog::setConnection(const QString &c)
848 {
849     m_lineEdit->setText(c);
850     m_okButton->setEnabled(!c.isEmpty());
851 }
852
853 AddressDialog::AddressDialog(QWidget *parent) :
854         QDialog(parent),
855         m_lineEdit(new QLineEdit),
856         m_box(new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel))
857 {
858     setWindowTitle(tr("Select Start Address"));
859     setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
860     QHBoxLayout *hLayout = new QHBoxLayout;
861     hLayout->addWidget(new QLabel(tr("Enter an address: ")));
862     hLayout->addWidget(m_lineEdit);
863     QVBoxLayout *vLayout = new QVBoxLayout;
864     vLayout->addLayout(hLayout);
865     vLayout->addWidget(m_box);
866     setLayout(vLayout);
867
868     connect(m_box, SIGNAL(accepted()), this, SLOT(accept()));
869     connect(m_box, SIGNAL(rejected()), this, SLOT(reject()));
870     connect(m_lineEdit, SIGNAL(returnPressed()), this, SLOT(accept()));
871     connect(m_lineEdit, SIGNAL(textChanged(QString)), this, SLOT(textChanged()));
872
873     setOkButtonEnabled(false);
874 }
875
876 void AddressDialog::setOkButtonEnabled(bool v)
877 {
878     m_box->button(QDialogButtonBox::Ok)->setEnabled(v);
879 }
880
881 bool AddressDialog::isOkButtonEnabled() const
882 {
883     return m_box->button(QDialogButtonBox::Ok)->isEnabled();
884 }
885
886 quint64 AddressDialog::address() const
887 {
888     return m_lineEdit->text().toULongLong(0, 16);
889 }
890
891 void AddressDialog::accept()
892 {
893     if (isOkButtonEnabled())
894         QDialog::accept();
895 }
896
897 void AddressDialog::textChanged()
898 {
899     setOkButtonEnabled(isValid());
900 }
901
902 bool AddressDialog::isValid() const
903 {
904     const QString text = m_lineEdit->text();
905     bool ok = false;
906     text.toULongLong(&ok, 16);
907     return ok;
908 }
909
910 ///////////////////////////////////////////////////////////////////////
911 //
912 // StartRemoteEngineDialog
913 //
914 ///////////////////////////////////////////////////////////////////////
915
916 StartRemoteEngineDialog::StartRemoteEngineDialog(QWidget *parent) :
917     QDialog(parent) ,
918     m_ui(new Ui::StartRemoteEngineDialog)
919 {
920     setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
921     m_ui->setupUi(this);
922     m_ui->host->setCompleter(new HistoryCompleter(m_ui->host));
923     m_ui->username->setCompleter(new HistoryCompleter(m_ui->username));
924     m_ui->enginepath->setCompleter(new HistoryCompleter(m_ui->enginepath));
925     m_ui->inferiorpath->setCompleter(new HistoryCompleter(m_ui->inferiorpath));
926     connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
927     connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
928 }
929
930 StartRemoteEngineDialog::~StartRemoteEngineDialog()
931 {
932 }
933
934 QString StartRemoteEngineDialog::host() const
935 {
936     return m_ui->host->text();
937 }
938
939 QString StartRemoteEngineDialog::username() const
940 {
941     return m_ui->username->text();
942 }
943
944 QString StartRemoteEngineDialog::password() const
945 {
946     return m_ui->password->text();
947 }
948
949 QString StartRemoteEngineDialog::inferiorPath() const
950 {
951     return m_ui->inferiorpath->text();
952 }
953
954 QString StartRemoteEngineDialog::enginePath() const
955 {
956     return m_ui->enginepath->text();
957 }
958
959 } // namespace Internal
960 } // namespace Debugger