2 ******************************************************************************
4 * @file pathchooser.cpp
5 * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
6 * Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009.
8 * @see The GNU Public License (GPL) Version 3
12 *****************************************************************************/
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 3 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24 * You should have received a copy of the GNU General Public License along
25 * with this program; if not, write to the Free Software Foundation, Inc.,
26 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #include "pathchooser.h"
31 #include "basevalidatinglineedit.h"
32 #include "qtcassert.h"
34 #include <QtCore/QDebug>
35 #include <QtCore/QDir>
36 #include <QtCore/QFileInfo>
37 #include <QtCore/QSettings>
39 #include <QDesktopServices>
40 #include <QFileDialog>
41 #include <QHBoxLayout>
43 #include <QToolButton>
44 #include <QPushButton>
46 /*static*/ const char *const Utils::PathChooser::browseButtonLabel
=
48 QT_TRANSLATE_NOOP("Utils::PathChooser", "Choose...");
50 QT_TRANSLATE_NOOP("Utils::PathChooser", "Browse...");
54 // ------------------ PathValidatingLineEdit
55 class PathValidatingLineEdit
: public BaseValidatingLineEdit
{
57 explicit PathValidatingLineEdit(PathChooser
*chooser
, QWidget
*parent
= 0);
60 virtual bool validate(const QString
&value
, QString
*errorMessage
) const;
63 PathChooser
*m_chooser
;
66 PathValidatingLineEdit::PathValidatingLineEdit(PathChooser
*chooser
, QWidget
*parent
) :
67 BaseValidatingLineEdit(parent
),
70 QTC_ASSERT(chooser
, return );
73 bool PathValidatingLineEdit::validate(const QString
&value
, QString
*errorMessage
) const
75 return m_chooser
->validatePath(value
, errorMessage
);
78 // ------------------ PathChooserPrivate
79 struct PathChooserPrivate
{
80 PathChooserPrivate(PathChooser
*chooser
);
82 QHBoxLayout
*m_hLayout
;
83 PathValidatingLineEdit
*m_lineEdit
;
84 PathChooser::Kind m_acceptingKind
;
85 QString m_dialogTitleOverride
;
86 QString m_dialogFilter
;
87 QString m_initialBrowsePathOverride
;
90 PathChooserPrivate::PathChooserPrivate(PathChooser
*chooser
) :
91 m_hLayout(new QHBoxLayout
),
92 m_lineEdit(new PathValidatingLineEdit(chooser
)),
93 m_acceptingKind(PathChooser::Directory
)
96 PathChooser::PathChooser(QWidget
*parent
) :
98 m_d(new PathChooserPrivate(this))
100 m_d
->m_hLayout
->setContentsMargins(0, 0, 0, 0);
102 connect(m_d
->m_lineEdit
, SIGNAL(validReturnPressed()), this, SIGNAL(returnPressed()));
103 connect(m_d
->m_lineEdit
, SIGNAL(textChanged(QString
)), this, SIGNAL(changed(QString
)));
104 connect(m_d
->m_lineEdit
, SIGNAL(validChanged()), this, SIGNAL(validChanged()));
105 connect(m_d
->m_lineEdit
, SIGNAL(validChanged(bool)), this, SIGNAL(validChanged(bool)));
106 connect(m_d
->m_lineEdit
, SIGNAL(editingFinished()), this, SIGNAL(editingFinished()));
108 m_d
->m_lineEdit
->setMinimumWidth(50);
109 m_d
->m_hLayout
->addWidget(m_d
->m_lineEdit
);
110 m_d
->m_hLayout
->setSizeConstraint(QLayout::SetMinimumSize
);
112 addButton(tr(browseButtonLabel
), this, SLOT(slotBrowse()));
114 setLayout(m_d
->m_hLayout
);
115 setFocusProxy(m_d
->m_lineEdit
);
118 PathChooser::~PathChooser()
123 void PathChooser::addButton(const QString
&text
, QObject
*receiver
, const char *slotFunc
)
126 QPushButton
*button
= new QPushButton
;
128 QToolButton
*button
= new QToolButton
;
130 button
->setText(text
);
131 connect(button
, SIGNAL(clicked()), receiver
, slotFunc
);
132 m_d
->m_hLayout
->addWidget(button
);
135 QAbstractButton
*PathChooser::buttonAtIndex(int index
) const
137 return findChildren
<QAbstractButton
*>().at(index
);
140 QString
PathChooser::path() const
142 return m_d
->m_lineEdit
->text();
145 void PathChooser::setPath(const QString
&path
)
147 m_d
->m_lineEdit
->setText(QDir::toNativeSeparators(path
));
150 void PathChooser::slotBrowse()
152 emit
beforeBrowsing();
154 QString predefined
= path();
156 if ((predefined
.isEmpty() || !QFileInfo(predefined
).isDir())
157 && !m_d
->m_initialBrowsePathOverride
.isNull()) {
158 predefined
= m_d
->m_initialBrowsePathOverride
;
160 if (!QFileInfo(predefined
).isDir()) {
165 if (predefined
.startsWith(":")) {
169 // Prompt for a file/dir
172 switch (m_d
->m_acceptingKind
) {
173 case PathChooser::Directory
:
174 newPath
= QFileDialog::getExistingDirectory(this,
175 makeDialogTitle(tr("Choose a directory")), predefined
);
178 case PathChooser::File
: // fall through
179 case PathChooser::Command
:
180 newPath
= QFileDialog::getOpenFileName(this,
181 makeDialogTitle(tr("Choose a file")), predefined
,
182 m_d
->m_dialogFilter
);
189 // Delete trailing slashes unless it is "/"|"\\", only
190 if (!newPath
.isEmpty()) {
191 newPath
= QDir::toNativeSeparators(newPath
);
192 if (newPath
.size() > 1 && newPath
.endsWith(QDir::separator())) {
193 newPath
.truncate(newPath
.size() - 1);
198 emit
browsingFinished();
201 bool PathChooser::isValid() const
203 return m_d
->m_lineEdit
->isValid();
206 QString
PathChooser::errorMessage() const
208 return m_d
->m_lineEdit
->errorMessage();
211 bool PathChooser::validatePath(const QString
&path
, QString
*errorMessage
)
213 if (path
.isEmpty()) {
215 *errorMessage
= tr("The path must not be empty.");
220 const QFileInfo
fi(path
);
221 const bool isDir
= fi
.isDir();
224 switch (m_d
->m_acceptingKind
) {
225 case PathChooser::Directory
: // fall through
226 case PathChooser::File
:
229 *errorMessage
= tr("The path '%1' does not exist.").arg(path
);
235 case PathChooser::Command
: // fall through
240 // Check expected kind
241 switch (m_d
->m_acceptingKind
) {
242 case PathChooser::Directory
:
245 *errorMessage
= tr("The path '%1' is not a directory.").arg(path
);
251 case PathChooser::File
:
254 *errorMessage
= tr("The path '%1' is not a file.").arg(path
);
260 case PathChooser::Command
:
261 // TODO do proper command validation
262 // i.e. search $PATH for a matching file
272 QString
PathChooser::label()
277 QString
PathChooser::homePath()
280 // Return 'users/<name>/Documents' on Windows, since Windows explorer
281 // does not let people actually display the contents of their home
282 // directory. Alternatively, create a QtCreator-specific directory?
283 return QStandardPaths::displayName(QStandardPaths::DocumentsLocation
);
286 return QDir::homePath();
291 void PathChooser::setExpectedKind(Kind expected
)
293 m_d
->m_acceptingKind
= expected
;
296 PathChooser::Kind
PathChooser::expectedKind() const
298 return m_d
->m_acceptingKind
;
301 void PathChooser::setPromptDialogTitle(const QString
&title
)
303 m_d
->m_dialogTitleOverride
= title
;
306 QString
PathChooser::promptDialogTitle() const
308 return m_d
->m_dialogTitleOverride
;
311 void PathChooser::setPromptDialogFilter(const QString
&filter
)
313 m_d
->m_dialogFilter
= filter
;
316 QString
PathChooser::promptDialogFilter() const
318 return m_d
->m_dialogFilter
;
321 void PathChooser::setInitialBrowsePathBackup(const QString
&path
)
323 m_d
->m_initialBrowsePathOverride
= path
;
326 QString
PathChooser::makeDialogTitle(const QString
&title
)
328 if (m_d
->m_dialogTitleOverride
.isNull()) {
331 return m_d
->m_dialogTitleOverride
;