kitmanagerconfigwidget.cpp 11.8 KB
Newer Older
hjk's avatar
hjk committed
1
/****************************************************************************
Tobias Hunger's avatar
Tobias Hunger committed
2
**
3
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
hjk's avatar
hjk committed
4
** Contact: http://www.qt-project.org/legal
Tobias Hunger's avatar
Tobias Hunger committed
5
**
hjk's avatar
hjk committed
6
** This file is part of Qt Creator.
Tobias Hunger's avatar
Tobias Hunger committed
7
**
hjk's avatar
hjk committed
8
9
10
11
12
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
Eike Ziller's avatar
Eike Ziller committed
13
14
** conditions see http://www.qt.io/licensing.  For further information
** use the contact form at http://www.qt.io/contact-us.
Tobias Hunger's avatar
Tobias Hunger committed
15
16
**
** GNU Lesser General Public License Usage
hjk's avatar
hjk committed
17
** Alternatively, this file may be used under the terms of the GNU Lesser
Eike Ziller's avatar
Eike Ziller committed
18
19
20
21
22
23
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file.  Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
hjk's avatar
hjk committed
24
25
26
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
Tobias Hunger's avatar
Tobias Hunger committed
27
28
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
29
****************************************************************************/
Tobias Hunger's avatar
Tobias Hunger committed
30

Tobias Hunger's avatar
Tobias Hunger committed
31
#include "kitmanagerconfigwidget.h"
32
#include "projectexplorerconstants.h"
Tobias Hunger's avatar
Tobias Hunger committed
33

Tobias Hunger's avatar
Tobias Hunger committed
34
#include "kit.h"
Tobias Hunger's avatar
Tobias Hunger committed
35
#include "kitmanager.h"
36
#include "task.h"
Tobias Hunger's avatar
Tobias Hunger committed
37

38
#include <utils/detailswidget.h>
hjk's avatar
hjk committed
39
#include <utils/qtcassert.h>
40
#include <utils/stringutils.h>
41

42
#include <QAction>
43
44
#include <QRegularExpression>
#include <QRegularExpressionValidator>
Tobias Hunger's avatar
Tobias Hunger committed
45
#include <QFileDialog>
Eike Ziller's avatar
Eike Ziller committed
46
47
#include <QGridLayout>
#include <QLabel>
48
#include <QLineEdit>
hjk's avatar
hjk committed
49
#include <QPainter>
Eike Ziller's avatar
Eike Ziller committed
50
#include <QToolButton>
51
#include <QScrollArea>
Tobias Hunger's avatar
Tobias Hunger committed
52
#include <QSizePolicy>
Eike Ziller's avatar
Eike Ziller committed
53
#include <QStyle>
Tobias Hunger's avatar
Tobias Hunger committed
54

Tobias Hunger's avatar
Tobias Hunger committed
55
56
static const char WORKING_COPY_KIT_ID[] = "modified kit";

Tobias Hunger's avatar
Tobias Hunger committed
57
58
59
namespace ProjectExplorer {
namespace Internal {

hjk's avatar
hjk committed
60
KitManagerConfigWidget::KitManagerConfigWidget(Kit *k) :
Eike Ziller's avatar
Eike Ziller committed
61
62
    m_layout(new QGridLayout),
    m_iconButton(new QToolButton),
63
    m_nameEdit(new QLineEdit),
64
    m_fileSystemFriendlyNameLineEdit(new QLineEdit),
Tobias Hunger's avatar
Tobias Hunger committed
65
66
    m_kit(k),
    m_modifiedKit(new Kit(Core::Id(WORKING_COPY_KIT_ID))),
67
68
    m_fixingKit(false),
    m_hasUniqueName(true)
Tobias Hunger's avatar
Tobias Hunger committed
69
{
70
71
72
    static const Qt::Alignment alignment
            = static_cast<Qt::Alignment>(style()->styleHint(QStyle::SH_FormLayoutLabelAlignment));

hjk's avatar
hjk committed
73
74
75
76
    m_layout->addWidget(m_nameEdit, 0, WidgetColumn);
    m_layout->addWidget(m_iconButton, 0, ButtonColumn);
    setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);

77
78
79
80
81
82
83
84
    QString toolTip =
        tr("<html><head/><body><p>The name of the kit suitable for generating "
           "directory names. This value is used for the variable <i>%1</i>, "
           "which for example determines the name of the shadow build directory."
           "</p></body></html>").arg(QLatin1String(Constants::VAR_CURRENTKIT_FILESYSTEMNAME));
    QLabel *label = createLabel(tr("File system name:"), toolTip);
    m_layout->addWidget(label, 1, LabelColumn, alignment);
    m_fileSystemFriendlyNameLineEdit->setToolTip(toolTip);
85
    QRegularExpression fileSystemFriendlyNameRegexp(QLatin1String("^[A-Za-z0-9_-]*$"));
86
    Q_ASSERT(fileSystemFriendlyNameRegexp.isValid());
87
    m_fileSystemFriendlyNameLineEdit->setValidator(new QRegularExpressionValidator(fileSystemFriendlyNameRegexp, m_fileSystemFriendlyNameLineEdit));
88
    m_layout->addWidget(m_fileSystemFriendlyNameLineEdit, 1, WidgetColumn);
89
    connect(m_fileSystemFriendlyNameLineEdit, &QLineEdit::textChanged, this, &KitManagerConfigWidget::setFileSystemFriendlyName);
90

hjk's avatar
hjk committed
91
92
    QWidget *inner = new QWidget;
    inner->setLayout(m_layout);
93
94

    QScrollArea *scroll = new QScrollArea;
hjk's avatar
hjk committed
95
    scroll->setWidget(inner);
96
97
98
99
    scroll->setFrameShape(QFrame::NoFrame);
    scroll->setWidgetResizable(true);
    scroll->setFocusPolicy(Qt::NoFocus);

hjk's avatar
hjk committed
100
101
102
    QGridLayout *mainLayout = new QGridLayout(this);
    mainLayout->setMargin(1);
    mainLayout->addWidget(scroll, 0, 0);
103

104
105
    toolTip = tr("Kit name and icon.");
    label = createLabel(tr("Name:"), toolTip);
106
    m_layout->addWidget(label, 0, LabelColumn, alignment);
hjk's avatar
hjk committed
107
    m_iconButton->setToolTip(toolTip);
Tobias Hunger's avatar
Tobias Hunger committed
108
109
110

    discard();

111
112
113
114
    connect(m_iconButton, &QAbstractButton::clicked,
            this, &KitManagerConfigWidget::setIcon);
    connect(m_nameEdit, &QLineEdit::textChanged,
            this, &KitManagerConfigWidget::setDisplayName);
Tobias Hunger's avatar
Tobias Hunger committed
115

116
117
118
119
120
    KitManager *km = KitManager::instance();
    connect(km, &KitManager::unmanagedKitUpdated,
            this, &KitManagerConfigWidget::workingCopyWasUpdated);
    connect(km, &KitManager::kitUpdated,
            this, &KitManagerConfigWidget::kitWasUpdated);
Tobias Hunger's avatar
Tobias Hunger committed
121
122
123
124
}

KitManagerConfigWidget::~KitManagerConfigWidget()
{
Tobias Hunger's avatar
Tobias Hunger committed
125
126
    qDeleteAll(m_widgets);
    m_widgets.clear();
127
128
    qDeleteAll(m_actions);
    m_actions.clear();
Tobias Hunger's avatar
Tobias Hunger committed
129

130
    KitManager::deleteKit(m_modifiedKit);
Tobias Hunger's avatar
Tobias Hunger committed
131
    // Make sure our workingCopy did not get registered somehow:
132
    foreach (const Kit *k, KitManager::kits())
hjk's avatar
hjk committed
133
        QTC_CHECK(k->id() != Core::Id(WORKING_COPY_KIT_ID));
Tobias Hunger's avatar
Tobias Hunger committed
134
135
}

Tobias Hunger's avatar
Tobias Hunger committed
136
QString KitManagerConfigWidget::displayName() const
Tobias Hunger's avatar
Tobias Hunger committed
137
{
138
    return m_modifiedKit->displayName();
Tobias Hunger's avatar
Tobias Hunger committed
139
140
}

Tobias Hunger's avatar
Tobias Hunger committed
141
void KitManagerConfigWidget::apply()
Tobias Hunger's avatar
Tobias Hunger committed
142
{
Jing Bai's avatar
Jing Bai committed
143
    bool mustSetDefault = m_isDefaultKit;
Tobias Hunger's avatar
Tobias Hunger committed
144
145
146
147
148
    bool mustRegister = false;
    if (!m_kit) {
        mustRegister = true;
        m_kit = new Kit;
    }
149
    m_kit->copyFrom(m_modifiedKit); //m_isDefaultKit is reset in discard() here.
Tobias Hunger's avatar
Tobias Hunger committed
150
    if (mustRegister)
151
        KitManager::registerKit(m_kit);
Tobias Hunger's avatar
Tobias Hunger committed
152

Jing Bai's avatar
Jing Bai committed
153
    if (mustSetDefault)
154
        KitManager::setDefaultKit(m_kit);
Jing Bai's avatar
Jing Bai committed
155
156

    m_isDefaultKit = mustSetDefault;
Tobias Hunger's avatar
Tobias Hunger committed
157
    emit dirty();
Tobias Hunger's avatar
Tobias Hunger committed
158
159
}

Tobias Hunger's avatar
Tobias Hunger committed
160
void KitManagerConfigWidget::discard()
Tobias Hunger's avatar
Tobias Hunger committed
161
{
Tobias Hunger's avatar
Tobias Hunger committed
162
163
    if (m_kit) {
        m_modifiedKit->copyFrom(m_kit);
164
        m_isDefaultKit = (m_kit == KitManager::defaultKit());
Tobias Hunger's avatar
Tobias Hunger committed
165
166
167
168
169
170
    } else {
        // This branch will only ever get reached once during setup of widget for a not-yet-existing
        // kit.
        m_isDefaultKit = false;
    }
    m_iconButton->setIcon(m_modifiedKit->icon());
171
    m_nameEdit->setText(m_modifiedKit->unexpandedDisplayName());
172
    m_fileSystemFriendlyNameLineEdit->setText(m_modifiedKit->customFileSystemFriendlyName());
Tobias Hunger's avatar
Tobias Hunger committed
173
    emit dirty();
Tobias Hunger's avatar
Tobias Hunger committed
174
175
}

Tobias Hunger's avatar
Tobias Hunger committed
176
bool KitManagerConfigWidget::isDirty() const
Tobias Hunger's avatar
Tobias Hunger committed
177
{
Tobias Hunger's avatar
Tobias Hunger committed
178
179
    return !m_kit
            || !m_kit->isEqual(m_modifiedKit)
180
            || m_isDefaultKit != (KitManager::defaultKit() == m_kit);
Tobias Hunger's avatar
Tobias Hunger committed
181
182
183
184
185
186
187
}

bool KitManagerConfigWidget::isValid() const
{
    return m_modifiedKit->isValid();
}

188
189
bool KitManagerConfigWidget::hasWarning() const
{
190
    return m_modifiedKit->hasWarning() || !m_hasUniqueName;
191
192
}

Tobias Hunger's avatar
Tobias Hunger committed
193
194
QString KitManagerConfigWidget::validityMessage() const
{
195
196
197
198
199
200
    QList<Task> tmp;
    if (!m_hasUniqueName) {
        tmp.append(Task(Task::Warning, tr("Display name is not unique."), Utils::FileName(), -1,
                        ProjectExplorer::Constants::TASK_CATEGORY_COMPILE));
    }
    return m_modifiedKit->toHtml(tmp);
Tobias Hunger's avatar
Tobias Hunger committed
201
202
}

203
void KitManagerConfigWidget::addConfigWidget(KitConfigWidget *widget)
Tobias Hunger's avatar
Tobias Hunger committed
204
{
hjk's avatar
hjk committed
205
206
207
208
209
210
    QTC_ASSERT(widget, return);
    QTC_ASSERT(!m_widgets.contains(widget), return);

    QString name = widget->displayName();
    QString toolTip = widget->toolTip();

211
212
    QAction *action = new QAction(tr("Mark as Mutable"), 0);
    action->setCheckable(true);
Tobias Hunger's avatar
Tobias Hunger committed
213
    action->setData(QVariant::fromValue(qobject_cast<QObject *>(widget)));
214
215
216
217
    action->setChecked(widget->isMutable());
    action->setEnabled(!widget->isSticky());
    widget->mainWidget()->addAction(action);
    widget->mainWidget()->setContextMenuPolicy(Qt::ActionsContextMenu);
218
    connect(action, &QAction::toggled, this, &KitManagerConfigWidget::updateMutableState);
219
220
    m_actions << action;

hjk's avatar
hjk committed
221
222
223
224
    int row = m_layout->rowCount();
    m_layout->addWidget(widget->mainWidget(), row, WidgetColumn);
    if (QWidget *button = widget->buttonWidget())
        m_layout->addWidget(button, row, ButtonColumn);
Tobias Hunger's avatar
Tobias Hunger committed
225

226
227
228
229
    static const Qt::Alignment alignment
        = static_cast<Qt::Alignment>(style()->styleHint(QStyle::SH_FormLayoutLabelAlignment));
    QLabel *label = createLabel(name, toolTip);
    m_layout->addWidget(label, row, LabelColumn, alignment);
Tobias Hunger's avatar
Tobias Hunger committed
230
    m_widgets.append(widget);
231
232
233
234
235
236
237
238
239
240
241
242
243
244
    m_labels.append(label);
}

void KitManagerConfigWidget::updateVisibility()
{
    int count = m_widgets.count();
    for (int i = 0; i < count; ++i) {
        KitConfigWidget *widget = m_widgets.at(i);
        bool visible = widget->visibleInKit();
        widget->mainWidget()->setVisible(visible);
        if (widget->buttonWidget())
            widget->buttonWidget()->setVisible(visible);
        m_labels.at(i)->setVisible(visible);
    }
Tobias Hunger's avatar
Tobias Hunger committed
245
246
}

247
248
249
250
251
void KitManagerConfigWidget::setHasUniqueName(bool unique)
{
    m_hasUniqueName = unique;
}

252
void KitManagerConfigWidget::makeStickySubWidgetsReadOnly()
Tobias Hunger's avatar
Tobias Hunger committed
253
{
254
255
256
257
    foreach (KitConfigWidget *w, m_widgets) {
        if (w->isSticky())
            w->makeReadOnly();
    }
Tobias Hunger's avatar
Tobias Hunger committed
258
259
}

Tobias Hunger's avatar
Tobias Hunger committed
260
261
262
263
264
265
266
267
268
269
270
271
Kit *KitManagerConfigWidget::workingCopy() const
{
    return m_modifiedKit;
}

bool KitManagerConfigWidget::configures(Kit *k) const
{
    return m_kit == k;
}

void KitManagerConfigWidget::setIsDefaultKit(bool d)
{
Jing Bai's avatar
Jing Bai committed
272
    if (m_isDefaultKit == d)
Tobias Hunger's avatar
Tobias Hunger committed
273
274
275
276
277
278
279
280
281
282
283
284
285
286
        return;
    m_isDefaultKit = d;
    emit dirty();
}

bool KitManagerConfigWidget::isDefaultKit() const
{
    return m_isDefaultKit;
}

void KitManagerConfigWidget::removeKit()
{
    if (!m_kit)
        return;
287
    KitManager::deregisterKit(m_kit);
Tobias Hunger's avatar
Tobias Hunger committed
288
289
}

Tobias Hunger's avatar
Tobias Hunger committed
290
void KitManagerConfigWidget::setIcon()
Tobias Hunger's avatar
Tobias Hunger committed
291
{
292
293
294
295
    const Utils::FileName path = Utils::FileName::fromString(
                QFileDialog::getOpenFileName(this, tr("Select Icon"),
                                             m_modifiedKit->iconPath().toString(),
                                             tr("Images (*.png *.xpm *.jpg)")));
Tobias Hunger's avatar
Tobias Hunger committed
296
297
298
    if (path.isEmpty())
        return;

299
    const QIcon icon = Kit::icon(path);
Tobias Hunger's avatar
Tobias Hunger committed
300
301
302
303
    if (icon.isNull())
        return;

    m_iconButton->setIcon(icon);
Tobias Hunger's avatar
Tobias Hunger committed
304
    m_modifiedKit->setIconPath(path);
Tobias Hunger's avatar
Tobias Hunger committed
305
306
307
    emit dirty();
}

Tobias Hunger's avatar
Tobias Hunger committed
308
309
void KitManagerConfigWidget::setDisplayName()
{
310
    int pos = m_nameEdit->cursorPosition();
311
    m_modifiedKit->setUnexpandedDisplayName(m_nameEdit->text());
312
    m_nameEdit->setCursorPosition(pos);
Tobias Hunger's avatar
Tobias Hunger committed
313
314
}

315
316
317
318
319
320
321
void KitManagerConfigWidget::setFileSystemFriendlyName()
{
    const int pos = m_fileSystemFriendlyNameLineEdit->cursorPosition();
    m_modifiedKit->setCustomFileSystemFriendlyName(m_fileSystemFriendlyNameLineEdit->text());
    m_fileSystemFriendlyNameLineEdit->setCursorPosition(pos);
}

Tobias Hunger's avatar
Tobias Hunger committed
322
323
324
325
326
327
328
329
330
331
332
void KitManagerConfigWidget::workingCopyWasUpdated(Kit *k)
{
    if (k != m_modifiedKit || m_fixingKit)
        return;

    m_fixingKit = true;
    k->fix();
    m_fixingKit = false;

    foreach (KitConfigWidget *w, m_widgets)
        w->refresh();
333
334
335
336

    if (k->unexpandedDisplayName() != m_nameEdit->text())
        m_nameEdit->setText(k->unexpandedDisplayName());

337
    m_fileSystemFriendlyNameLineEdit->setText(k->customFileSystemFriendlyName());
Tobias Hunger's avatar
Tobias Hunger committed
338
    m_iconButton->setIcon(k->icon());
339
    updateVisibility();
Tobias Hunger's avatar
Tobias Hunger committed
340
341
342
343
344
345
346
    emit dirty();
}

void KitManagerConfigWidget::kitWasUpdated(Kit *k)
{
    if (m_kit == k)
        discard();
347
    updateVisibility();
Tobias Hunger's avatar
Tobias Hunger committed
348
349
}

350
351
352
353
354
355
356
357
358
359
360
361
void KitManagerConfigWidget::updateMutableState()
{
    QAction *action = qobject_cast<QAction *>(sender());
    if (!action)
        return;
    KitConfigWidget *widget = qobject_cast<KitConfigWidget *>(action->data().value<QObject *>());
    if (!widget)
        return;
    widget->setMutable(action->isChecked());
    emit dirty();
}

362
QLabel *KitManagerConfigWidget::createLabel(const QString &name, const QString &toolTip)
363
364
365
{
    QLabel *label = new QLabel(name);
    label->setToolTip(toolTip);
366
    return label;
367
368
}

hjk's avatar
hjk committed
369
void KitManagerConfigWidget::paintEvent(QPaintEvent *)
370
{
hjk's avatar
hjk committed
371
372
373
374
    QPainter p(this);
    if (m_background.size() != size())
        m_background = Utils::DetailsWidget::createBackground(size(), 0, this);
    p.drawPixmap(rect(), m_background);
375
376
}

Tobias Hunger's avatar
Tobias Hunger committed
377
378
} // namespace Internal
} // namespace ProjectExplorer