genericprojectwizard.cpp 11.4 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact:  Qt Software Information (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
**
**************************************************************************/

Roberto Raggi's avatar
Roberto Raggi committed
30
#include "genericprojectwizard.h"
Roberto Raggi's avatar
Roberto Raggi committed
31
32
33

#include <coreplugin/icore.h>
#include <coreplugin/mimedatabase.h>
Roberto Raggi's avatar
Roberto Raggi committed
34
35
#include <projectexplorer/projectexplorer.h>

36
37
#include <utils/filenamevalidatinglineedit.h>
#include <utils/filewizardpage.h>
Roberto Raggi's avatar
Roberto Raggi committed
38
39
#include <utils/pathchooser.h>

Roberto Raggi's avatar
Roberto Raggi committed
40
#include <QtCore/QDir>
Roberto Raggi's avatar
Roberto Raggi committed
41
42
#include <QtCore/QtDebug>

43
#include <QtGui/QDirModel>
Roberto Raggi's avatar
Roberto Raggi committed
44
45
46
47
#include <QtGui/QFormLayout>
#include <QtGui/QListView>
#include <QtGui/QTreeView>

Roberto Raggi's avatar
Roberto Raggi committed
48
49
50
using namespace GenericProjectManager::Internal;
using namespace Core::Utils;

Roberto Raggi's avatar
Roberto Raggi committed
51
52
namespace {

53
class DirModel : public QDirModel
Roberto Raggi's avatar
Roberto Raggi committed
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
{
public:
    DirModel(QObject *parent)
        : QDirModel(parent)
    { setFilter(QDir::Dirs | QDir::NoDotAndDotDot); }

    virtual ~DirModel()
    { }

public:
    virtual int columnCount(const QModelIndex &) const
    { return 1; }

    virtual Qt::ItemFlags flags(const QModelIndex &index) const
    { return QDirModel::flags(index) | Qt::ItemIsUserCheckable; }

    virtual QVariant data(const QModelIndex &index, int role) const
    {
        if (index.column() == 0 && role == Qt::CheckStateRole) {
73
            if (m_selectedPaths.contains(index))
Roberto Raggi's avatar
Roberto Raggi committed
74
75
76
77
78
79
80
81
82
83
84
85
                return Qt::Checked;

            return Qt::Unchecked;
        }

        return QDirModel::data(index, role);
    }

    virtual bool setData(const QModelIndex &index, const QVariant &value, int role)
    {
        if (index.column() == 0 && role == Qt::CheckStateRole) {
            if (value.toBool())
86
                m_selectedPaths.insert(index);
Roberto Raggi's avatar
Roberto Raggi committed
87
            else
88
                m_selectedPaths.remove(index);
Roberto Raggi's avatar
Roberto Raggi committed
89
90
91
92
93
94
95
96

            return true;
        }

        return QDirModel::setData(index, value, role);
    }

    void clearSelectedPaths()
97
    { m_selectedPaths.clear(); }
Roberto Raggi's avatar
Roberto Raggi committed
98
99
100
101
102

    QSet<QString> selectedPaths() const
    {
        QSet<QString> paths;

103
        foreach (const QModelIndex &index, m_selectedPaths)
Roberto Raggi's avatar
Roberto Raggi committed
104
105
106
107
108
109
            paths.insert(filePath(index));

        return paths;
    }

private:
110
    QSet<QModelIndex> m_selectedPaths;
Roberto Raggi's avatar
Roberto Raggi committed
111
112
113
114
115
116
117
118
119
120
121
122
};

} // end of anonymous namespace


//////////////////////////////////////////////////////////////////////////////
// GenericProjectWizardDialog
//////////////////////////////////////////////////////////////////////////////


GenericProjectWizardDialog::GenericProjectWizardDialog(QWidget *parent)
    : QWizard(parent)
Roberto Raggi's avatar
Roberto Raggi committed
123
{
124
    setWindowTitle(tr("Import of Makefile-based Project"));
Roberto Raggi's avatar
Roberto Raggi committed
125
126

    // first page
127
    m_firstPage = new FileWizardPage;
128
    m_firstPage->setTitle(tr("Generic Project"));
129
130
    m_firstPage->setNameLabel(tr("Project name:"));
    m_firstPage->setPathLabel(tr("Location:"));
Roberto Raggi's avatar
Roberto Raggi committed
131

132
    addPage(m_firstPage);
Roberto Raggi's avatar
Roberto Raggi committed
133
134
135
136
137
138
139
140

#if 0
    // second page
    QWizardPage *secondPage = new QWizardPage;
    secondPage->setTitle(tr("Second Page Title"));

    QFormLayout *secondPageLayout = new QFormLayout(secondPage);

141
142
143
    m_dirView = new QTreeView;
    m_dirModel = new DirModel(this);
    m_dirView->setModel(_dirModel);
Roberto Raggi's avatar
Roberto Raggi committed
144
145
146
147
148
149
150
151
152
153
154
155
156
157

    Core::ICore *core = Core::ICore::instance();
    Core::MimeDatabase *mimeDatabase = core->mimeDatabase();

    const QStringList suffixes = mimeDatabase->suffixes();

    QStringList nameFilters;
    foreach (const QString &suffix, suffixes) {
        QString nameFilter;
        nameFilter.append(QLatin1String("*."));
        nameFilter.append(suffix);
        nameFilters.append(nameFilter);
    }

158
159
160
161
    m_filesView = new QListView;
    m_filesModel = new QDirModel(this);
    m_filesModel->setNameFilters(nameFilters);
    m_filesModel->setFilter(QDir::Files);
Roberto Raggi's avatar
Roberto Raggi committed
162
163
164
165
166
167
168

    connect(_dirView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
            this, SLOT(updateFilesView(QModelIndex,QModelIndex)));

    secondPageLayout->addRow(_dirView);
    secondPageLayout->addRow(_filesView);

169
    m_secondPageId = addPage(secondPage);
Roberto Raggi's avatar
Roberto Raggi committed
170
#endif
Roberto Raggi's avatar
Roberto Raggi committed
171
172
}

Roberto Raggi's avatar
Roberto Raggi committed
173
174
175
176
GenericProjectWizardDialog::~GenericProjectWizardDialog()
{ }

QString GenericProjectWizardDialog::path() const
177
178
179
180
{
    return m_firstPage->path();
}

181
182
183
184
185
void GenericProjectWizardDialog::setPath(const QString &path)
{
    m_firstPage->setPath(path);
}

186
187
188
189
QString GenericProjectWizardDialog::projectName() const
{
    return m_firstPage->name();
}
Roberto Raggi's avatar
Roberto Raggi committed
190
191
192

void GenericProjectWizardDialog::updateFilesView(const QModelIndex &current,
                                                 const QModelIndex &)
Roberto Raggi's avatar
Roberto Raggi committed
193
{
Roberto Raggi's avatar
Roberto Raggi committed
194
    if (! current.isValid())
195
        m_filesView->setModel(0);
Roberto Raggi's avatar
Roberto Raggi committed
196
197

    else {
198
        const QString selectedPath = m_dirModel->filePath(current);
Roberto Raggi's avatar
Roberto Raggi committed
199

200
201
        if (! m_filesView->model())
            m_filesView->setModel(m_filesModel);
Roberto Raggi's avatar
Roberto Raggi committed
202

203
        m_filesView->setRootIndex(m_filesModel->index(selectedPath));
Roberto Raggi's avatar
Roberto Raggi committed
204
205
206
207
208
    }
}

void GenericProjectWizardDialog::initializePage(int id)
{
209
    Q_UNUSED(id)
210
#if 0
211
    if (id == m_secondPageId) {
Roberto Raggi's avatar
Roberto Raggi committed
212
213
        using namespace Core::Utils;

214
        const QString projectPath = m_pathChooser->path();
Roberto Raggi's avatar
Roberto Raggi committed
215
216

        QDirModel *dirModel = qobject_cast<QDirModel *>(_dirView->model());
217
        m_dirView->setRootIndex(dirModel->index(projectPath));
Roberto Raggi's avatar
Roberto Raggi committed
218
    }
219
#endif
Roberto Raggi's avatar
Roberto Raggi committed
220
221
222
223
224
225
}

bool GenericProjectWizardDialog::validateCurrentPage()
{
    using namespace Core::Utils;

226
227
#if 0
    if (currentId() == m_secondPageId) {
Roberto Raggi's avatar
Roberto Raggi committed
228
229
        return true;
    }
230
#endif
Roberto Raggi's avatar
Roberto Raggi committed
231
232

    return QWizard::validateCurrentPage();
Roberto Raggi's avatar
Roberto Raggi committed
233
234
}

Roberto Raggi's avatar
Roberto Raggi committed
235
236
237
238
239
240
241
GenericProjectWizard::GenericProjectWizard()
    : Core::BaseFileWizard(parameters())
{ }

GenericProjectWizard::~GenericProjectWizard()
{ }

Roberto Raggi's avatar
Roberto Raggi committed
242
243
244
Core::BaseFileWizardParameters GenericProjectWizard::parameters()
{
    static Core::BaseFileWizardParameters parameters(ProjectWizard);
Roberto Raggi's avatar
Roberto Raggi committed
245
    parameters.setIcon(QIcon(":/wizards/images/console.png"));
246
247
    parameters.setName(tr("Import of Makefile-based Project"));
    parameters.setDescription(tr("Creates a generic project, supporting any build system."));
Roberto Raggi's avatar
Roberto Raggi committed
248
249
    parameters.setCategory(QLatin1String("Projects"));
    parameters.setTrCategory(tr("Projects"));
Roberto Raggi's avatar
Roberto Raggi committed
250
251
252
253
254
255
256
    return parameters;
}

QWizard *GenericProjectWizard::createWizardDialog(QWidget *parent,
                                                  const QString &defaultPath,
                                                  const WizardPageList &extensionPages) const
{
Roberto Raggi's avatar
Roberto Raggi committed
257
    GenericProjectWizardDialog *wizard = new GenericProjectWizardDialog(parent);
Roberto Raggi's avatar
Roberto Raggi committed
258
259
    setupWizard(wizard);

260
261
    wizard->setPath(defaultPath);

Roberto Raggi's avatar
Roberto Raggi committed
262
263
    foreach (QWizardPage *p, extensionPages)
        wizard->addPage(p);
Roberto Raggi's avatar
Roberto Raggi committed
264

Roberto Raggi's avatar
Roberto Raggi committed
265
266
    return wizard;
}
Roberto Raggi's avatar
Roberto Raggi committed
267

Roberto Raggi's avatar
Roberto Raggi committed
268
269
270
271
272
273
274
275
void GenericProjectWizard::getFileList(const QDir &dir, const QString &projectRoot,
                                       const QStringList &suffixes,
                                       QStringList *files, QStringList *paths) const
{
    const QFileInfoList fileInfoList = dir.entryInfoList(QDir::Files |
                                                         QDir::Dirs |
                                                         QDir::NoDotAndDotDot |
                                                         QDir::NoSymLinks);
Roberto Raggi's avatar
Roberto Raggi committed
276

Roberto Raggi's avatar
Roberto Raggi committed
277
278
279
    foreach (const QFileInfo &fileInfo, fileInfoList) {
        QString filePath = fileInfo.absoluteFilePath();
        filePath = filePath.mid(projectRoot.length() + 1);
Roberto Raggi's avatar
Roberto Raggi committed
280

Roberto Raggi's avatar
Roberto Raggi committed
281
282
283
        if (fileInfo.isDir() && isValidDir(fileInfo)) {
            getFileList(QDir(fileInfo.absoluteFilePath()), projectRoot,
                        suffixes, files, paths);
Roberto Raggi's avatar
Roberto Raggi committed
284

Roberto Raggi's avatar
Roberto Raggi committed
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
            if (! paths->contains(filePath))
                paths->append(filePath);
        }

        else if (suffixes.contains(fileInfo.suffix()))
            files->append(filePath);
    }
}

bool GenericProjectWizard::isValidDir(const QFileInfo &fileInfo) const
{
    const QString fileName = fileInfo.fileName();
    const QString suffix = fileInfo.suffix();

    if (fileName.startsWith(QLatin1Char('.')))
        return false;

    else if (fileName == QLatin1String("CVS"))
        return false;    

    // ### user include/exclude

    return true;
Roberto Raggi's avatar
Roberto Raggi committed
308
309
310
311
312
}

Core::GeneratedFiles GenericProjectWizard::generateFiles(const QWizard *w,
                                                         QString *errorMessage) const
{
313
314
    Q_UNUSED(errorMessage)

Roberto Raggi's avatar
Roberto Raggi committed
315
316
317
    const GenericProjectWizardDialog *wizard = qobject_cast<const GenericProjectWizardDialog *>(w);
    const QString projectPath = wizard->path();
    const QDir dir(projectPath);
318
    const QString projectName = wizard->projectName();
319
320
321
322
    const QString creatorFileName = QFileInfo(dir, projectName + QLatin1String(".creator")).absoluteFilePath();
    const QString filesFileName = QFileInfo(dir, projectName + QLatin1String(".files")).absoluteFilePath();
    const QString includesFileName = QFileInfo(dir, projectName + QLatin1String(".includes")).absoluteFilePath();
    const QString configFileName = QFileInfo(dir, projectName + QLatin1String(".config")).absoluteFilePath();
Roberto Raggi's avatar
Roberto Raggi committed
323
324
325
326
327

    Core::ICore *core = Core::ICore::instance();
    Core::MimeDatabase *mimeDatabase = core->mimeDatabase();

    const QStringList suffixes = mimeDatabase->suffixes();
Roberto Raggi's avatar
Roberto Raggi committed
328

Roberto Raggi's avatar
Roberto Raggi committed
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
    QStringList sources, paths;
    getFileList(dir, projectPath, suffixes, &sources, &paths);

    Core::MimeType headerTy = mimeDatabase->findByType(QLatin1String("text/x-chdr"));

    QStringList nameFilters;
    foreach (const QRegExp &rx, headerTy.globPatterns())
        nameFilters.append(rx.pattern());

    QStringList includePaths;
    foreach (const QString &path, paths) {
        QFileInfo fileInfo(dir, path);
        QDir thisDir(fileInfo.absoluteFilePath());

        if (! thisDir.entryList(nameFilters, QDir::Files).isEmpty())
            includePaths.append(path);
    }
Roberto Raggi's avatar
Roberto Raggi committed
346

347
348
    Core::GeneratedFile generatedCreatorFile(creatorFileName);
    generatedCreatorFile.setContents(QLatin1String("[General]\n"));
Roberto Raggi's avatar
Roberto Raggi committed
349

350
351
352
353
354
355
356
357
    Core::GeneratedFile generatedFilesFile(filesFileName);
    generatedFilesFile.setContents(sources.join(QLatin1String("\n")));

    Core::GeneratedFile generatedIncludesFile(includesFileName);
    generatedIncludesFile.setContents(includePaths.join(QLatin1String("\n")));

    Core::GeneratedFile generatedConfigFile(configFileName);
    generatedConfigFile.setContents(QLatin1String("// ADD PREDEFINED MACROS HERE!\n"));
Roberto Raggi's avatar
Roberto Raggi committed
358

Roberto Raggi's avatar
Roberto Raggi committed
359
    Core::GeneratedFiles files;
360
361
362
363
    files.append(generatedFilesFile);
    files.append(generatedIncludesFile);
    files.append(generatedConfigFile);
    files.append(generatedCreatorFile);
Roberto Raggi's avatar
Roberto Raggi committed
364
365
366
367
368
369
370
371
372
373
374
375
376

    return files;
}

bool GenericProjectWizard::postGenerateFiles(const Core::GeneratedFiles &l, QString *errorMessage)
{
    // Post-Generate: Open the project
    const QString proFileName = l.back().path();
    if (!ProjectExplorer::ProjectExplorerPlugin::instance()->openProject(proFileName)) {
        *errorMessage = tr("The project %1 could not be opened.").arg(proFileName);
        return false;
    }
    return true;
Roberto Raggi's avatar
Roberto Raggi committed
377
378
}