OSDN Git Service

e9060e99f410ec20dc8c5584e03d5d7c43b96779
[qt-creator-jp/qt-creator-jp.git] / src / plugins / coreplugin / basefilewizard.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 "basefilewizard.h"
35
36 #include "coreconstants.h"
37 #include "icore.h"
38 #include "ifilewizardextension.h"
39 #include "mimedatabase.h"
40 #include "editormanager/editormanager.h"
41
42 #include <extensionsystem/pluginmanager.h>
43 #include <utils/filewizarddialog.h>
44 #include <utils/qtcassert.h>
45 #include <utils/stringutils.h>
46
47 #include <QtCore/QDir>
48 #include <QtCore/QFile>
49 #include <QtCore/QFileInfo>
50 #include <QtCore/QVector>
51 #include <QtCore/QDebug>
52 #include <QtCore/QSharedData>
53 #include <QtCore/QEventLoop>
54 #include <QtCore/QSharedPointer>
55 #include <QtCore/QScopedPointer>
56
57 #include <QtGui/QMessageBox>
58 #include <QtGui/QWizard>
59 #include <QtGui/QMainWindow>
60 #include <QtGui/QIcon>
61
62 enum { debugWizard = 0 };
63
64 namespace Core {
65
66 class GeneratedFilePrivate : public QSharedData
67 {
68 public:
69     GeneratedFilePrivate() : binary(false) {}
70     explicit GeneratedFilePrivate(const QString &p);
71     QString path;
72     QByteArray contents;
73     QString editorId;
74     bool binary;
75     GeneratedFile::Attributes attributes;
76 };
77
78 GeneratedFilePrivate::GeneratedFilePrivate(const QString &p) :
79     path(QDir::cleanPath(p)),
80     binary(false),
81     attributes(0)
82 {
83 }
84
85 GeneratedFile::GeneratedFile() :
86     m_d(new GeneratedFilePrivate)
87 {
88 }
89
90 GeneratedFile::GeneratedFile(const QString &p) :
91     m_d(new GeneratedFilePrivate(p))
92 {
93 }
94
95 GeneratedFile::GeneratedFile(const GeneratedFile &rhs) :
96     m_d(rhs.m_d)
97 {
98 }
99
100 GeneratedFile &GeneratedFile::operator=(const GeneratedFile &rhs)
101 {
102     if (this != &rhs)
103         m_d.operator=(rhs.m_d);
104     return *this;
105 }
106
107 GeneratedFile::~GeneratedFile()
108 {
109 }
110
111 QString GeneratedFile::path() const
112 {
113     return m_d->path;
114 }
115
116 void GeneratedFile::setPath(const QString &p)
117 {
118     m_d->path = QDir::cleanPath(p);
119 }
120
121 QString GeneratedFile::contents() const
122 {
123     return QString::fromUtf8(m_d->contents);
124 }
125
126 void GeneratedFile::setContents(const QString &c)
127 {
128     m_d->contents = c.toUtf8();
129 }
130
131 QByteArray GeneratedFile::binaryContents() const
132 {
133     return m_d->contents;
134 }
135
136 void GeneratedFile::setBinaryContents(const QByteArray &c)
137 {
138     m_d->contents = c;
139 }
140
141 bool GeneratedFile::isBinary() const
142 {
143     return m_d->binary;
144 }
145
146 void GeneratedFile::setBinary(bool b)
147 {
148     m_d->binary = b;
149 }
150
151 QString GeneratedFile::editorId() const
152 {
153     return m_d->editorId;
154 }
155
156 void GeneratedFile::setEditorId(const QString &k)
157 {
158     m_d->editorId = k;
159 }
160
161 bool GeneratedFile::write(QString *errorMessage) const
162 {
163     // Ensure the directory
164     const QFileInfo info(m_d->path);
165     const QDir dir = info.absoluteDir();
166     if (!dir.exists()) {
167         if (!dir.mkpath(dir.absolutePath())) {
168             *errorMessage = BaseFileWizard::tr("Unable to create the directory %1.").arg(dir.absolutePath());
169             return false;
170         }
171     }
172     // Write out
173     QFile file(m_d->path);
174
175     QIODevice::OpenMode flags = QIODevice::WriteOnly|QIODevice::Truncate;
176     if (!isBinary())
177         flags |= QIODevice::Text;
178
179     if (!file.open(flags)) {
180         *errorMessage = BaseFileWizard::tr("Unable to open %1 for writing: %2").arg(m_d->path, file.errorString());
181         return false;
182     }
183     if (file.write(m_d->contents) == -1) {
184         *errorMessage =  BaseFileWizard::tr("Error while writing to %1: %2").arg(m_d->path, file.errorString());
185         return false;
186     }
187     file.close();
188     return true;
189 }
190
191 GeneratedFile::Attributes GeneratedFile::attributes() const
192 {
193     return m_d->attributes;
194 }
195
196 void GeneratedFile::setAttributes(Attributes a)
197 {
198     m_d->attributes = a;
199 }
200
201 // ------------ BaseFileWizardParameterData
202 class BaseFileWizardParameterData : public QSharedData
203 {
204 public:
205     explicit BaseFileWizardParameterData(IWizard::WizardKind kind = IWizard::FileWizard);
206     void clear();
207
208     IWizard::WizardKind kind;
209     QIcon icon;
210     QString description;
211     QString displayName;
212     QString id;
213     QString category;
214     QString displayCategory;
215 };
216
217 BaseFileWizardParameterData::BaseFileWizardParameterData(IWizard::WizardKind k) :
218     kind(k)
219 {
220 }
221
222 void BaseFileWizardParameterData::clear()
223 {
224     kind = IWizard::FileWizard;
225     icon = QIcon();
226     description.clear();
227     displayName.clear();
228     id.clear();
229     category.clear();
230     displayCategory.clear();
231 }
232
233 BaseFileWizardParameters::BaseFileWizardParameters(IWizard::WizardKind kind) :
234    m_d(new BaseFileWizardParameterData(kind))
235 {
236 }
237
238 BaseFileWizardParameters::BaseFileWizardParameters(const BaseFileWizardParameters &rhs) :
239     m_d(rhs.m_d)
240 {
241 }
242
243 BaseFileWizardParameters &BaseFileWizardParameters::operator=(const BaseFileWizardParameters &rhs)
244 {
245     if (this != &rhs)
246         m_d.operator=(rhs.m_d);
247     return *this;
248 }
249
250 BaseFileWizardParameters::~BaseFileWizardParameters()
251 {
252 }
253
254 void BaseFileWizardParameters::clear()
255 {
256     m_d->clear();
257 }
258
259 CORE_EXPORT QDebug operator<<(QDebug d, const BaseFileWizardParameters &p)
260 {
261     d.nospace() << "Kind: " << p.kind() << " Id: " << p.id()
262                 << " Category: " << p.category()
263                 << " DisplayName: " << p.displayName()
264                 << " Description: " << p.description()
265                 << " DisplayCategory: " << p.displayCategory();
266     return d;
267 }
268
269 IWizard::WizardKind BaseFileWizardParameters::kind() const
270 {
271     return m_d->kind;
272 }
273
274 void BaseFileWizardParameters::setKind(IWizard::WizardKind k)
275 {
276     m_d->kind = k;
277 }
278
279 QIcon BaseFileWizardParameters::icon() const
280 {
281     return m_d->icon;
282 }
283
284 void BaseFileWizardParameters::setIcon(const QIcon &icon)
285 {
286     m_d->icon = icon;
287 }
288
289 QString BaseFileWizardParameters::description() const
290 {
291     return m_d->description;
292 }
293
294 void BaseFileWizardParameters::setDescription(const QString &v)
295 {
296     m_d->description = v;
297 }
298
299 QString BaseFileWizardParameters::displayName() const
300 {
301     return m_d->displayName;
302 }
303
304 void BaseFileWizardParameters::setDisplayName(const QString &v)
305 {
306     m_d->displayName = v;
307 }
308
309 QString BaseFileWizardParameters::id() const
310 {
311     return m_d->id;
312 }
313
314 void BaseFileWizardParameters::setId(const QString &v)
315 {
316     m_d->id = v;
317 }
318
319 QString BaseFileWizardParameters::category() const
320 {
321     return m_d->category;
322 }
323
324 void BaseFileWizardParameters::setCategory(const QString &v)
325 {
326     m_d->category = v;
327 }
328
329 QString BaseFileWizardParameters::displayCategory() const
330 {
331     return m_d->displayCategory;
332 }
333
334 void BaseFileWizardParameters::setDisplayCategory(const QString &v)
335 {
336     m_d->displayCategory = v;
337 }
338
339 /* WizardEventLoop: Special event loop that runs a QWizard and terminates if the page changes.
340  * Synopsis:
341  * \code
342     Wizard wizard(parent);
343     WizardEventLoop::WizardResult wr;
344     do {
345         wr = WizardEventLoop::execWizardPage(wizard);
346     } while (wr == WizardEventLoop::PageChanged);
347  * \endcode */
348
349 class WizardEventLoop : public QEventLoop
350 {
351     Q_OBJECT
352     Q_DISABLE_COPY(WizardEventLoop)
353     WizardEventLoop(QObject *parent);
354
355 public:
356     enum WizardResult { Accepted, Rejected , PageChanged };
357
358     static WizardResult execWizardPage(QWizard &w);
359
360 private slots:
361     void pageChanged(int);
362     void accepted();
363     void rejected();
364
365 private:
366     WizardResult execWizardPageI();
367
368     WizardResult m_result;
369 };
370
371 WizardEventLoop::WizardEventLoop(QObject *parent) :
372     QEventLoop(parent),
373     m_result(Rejected)
374 {
375 }
376
377 WizardEventLoop::WizardResult WizardEventLoop::execWizardPage(QWizard &wizard)
378 {
379     /* Install ourselves on the wizard. Main trick is here to connect
380      * to the page changed signal and quit() on it. */
381     WizardEventLoop *eventLoop = wizard.findChild<WizardEventLoop *>();
382     if (!eventLoop) {
383         eventLoop = new WizardEventLoop(&wizard);
384         connect(&wizard, SIGNAL(currentIdChanged(int)), eventLoop, SLOT(pageChanged(int)));
385         connect(&wizard, SIGNAL(accepted()), eventLoop, SLOT(accepted()));
386         connect(&wizard, SIGNAL(rejected()), eventLoop, SLOT(rejected()));
387         wizard.setAttribute(Qt::WA_ShowModal, true);
388         wizard.show();
389     }
390     const WizardResult result = eventLoop->execWizardPageI();
391     // Quitting?
392     if (result != PageChanged)
393         delete eventLoop;
394     if (debugWizard)
395         qDebug() << "WizardEventLoop::runWizard" << wizard.pageIds() << " returns " << result;
396
397     return result;
398 }
399
400 WizardEventLoop::WizardResult WizardEventLoop::execWizardPageI()
401 {
402     m_result = Rejected;
403     exec(QEventLoop::DialogExec);
404     return m_result;
405 }
406
407 void WizardEventLoop::pageChanged(int /*page*/)
408 {
409     m_result = PageChanged;
410     quit(); // !
411 }
412
413 void WizardEventLoop::accepted()
414 {
415     m_result = Accepted;
416     quit();
417 }
418
419 void WizardEventLoop::rejected()
420 {
421     m_result = Rejected;
422     quit();
423 }
424
425 // ---------------- BaseFileWizardPrivate
426 struct BaseFileWizardPrivate
427 {
428     explicit BaseFileWizardPrivate(const Core::BaseFileWizardParameters &parameters)
429       : m_parameters(parameters), m_wizardDialog(0)
430     {}
431
432     const Core::BaseFileWizardParameters m_parameters;
433     QWizard *m_wizardDialog;
434 };
435
436 // ---------------- Wizard
437 BaseFileWizard::BaseFileWizard(const BaseFileWizardParameters &parameters,
438                        QObject *parent) :
439     IWizard(parent),
440     m_d(new BaseFileWizardPrivate(parameters))
441 {
442 }
443
444 BaseFileWizard::~BaseFileWizard()
445 {
446     delete m_d;
447 }
448
449 IWizard::WizardKind  BaseFileWizard::kind() const
450 {
451     return m_d->m_parameters.kind();
452 }
453
454 QIcon BaseFileWizard::icon() const
455 {
456     return m_d->m_parameters.icon();
457 }
458
459 QString BaseFileWizard::description() const
460 {
461     return m_d->m_parameters.description();
462 }
463
464 QString BaseFileWizard::displayName() const
465 {
466     return m_d->m_parameters.displayName();
467 }
468
469 QString BaseFileWizard::id() const
470 {
471     return m_d->m_parameters.id();
472 }
473
474 QString BaseFileWizard::category() const
475 {
476     return m_d->m_parameters.category();
477 }
478
479 QString BaseFileWizard::displayCategory() const
480 {
481     return m_d->m_parameters.displayCategory();
482 }
483
484 void BaseFileWizard::runWizard(const QString &path, QWidget *parent)
485 {
486     QTC_ASSERT(!path.isEmpty(), return);
487
488     typedef  QList<IFileWizardExtension*> ExtensionList;
489
490     QString errorMessage;
491     // Compile extension pages, purge out unused ones
492     ExtensionList extensions = ExtensionSystem::PluginManager::instance()->getObjects<IFileWizardExtension>();
493     WizardPageList  allExtensionPages;
494     for (ExtensionList::iterator it = extensions.begin(); it !=  extensions.end(); ) {
495         const WizardPageList extensionPages = (*it)->extensionPages(this);
496         if (extensionPages.empty()) {
497             it = extensions.erase(it);
498         } else {
499             allExtensionPages += extensionPages;
500             ++it;
501         }
502     }
503
504     if (debugWizard)
505         qDebug() << Q_FUNC_INFO <<  path << parent << "exs" <<  extensions.size() << allExtensionPages.size();
506
507     QWizardPage *firstExtensionPage = 0;
508     if (!allExtensionPages.empty())
509         firstExtensionPage = allExtensionPages.front();
510
511     // Create dialog and run it. Ensure that the dialog is deleted when
512     // leaving the func, but not before the IFileWizardExtension::process
513     // has been called
514     const QScopedPointer<QWizard> wizard(createWizardDialog(parent, path, allExtensionPages));
515     QTC_ASSERT(!wizard.isNull(), return);
516
517     GeneratedFiles files;
518     // Run the wizard: Call generate files on switching to the first extension
519     // page is OR after 'Accepted' if there are no extension pages
520     while (true) {
521         const WizardEventLoop::WizardResult wr = WizardEventLoop::execWizardPage(*wizard);
522         if (wr == WizardEventLoop::Rejected) {
523             files.clear();
524             break;
525         }
526         const bool accepted = wr == WizardEventLoop::Accepted;
527         const bool firstExtensionPageHit = wr == WizardEventLoop::PageChanged
528                                            && wizard->page(wizard->currentId()) == firstExtensionPage;
529         const bool needGenerateFiles = firstExtensionPageHit || (accepted && allExtensionPages.empty());
530         if (needGenerateFiles) {
531             QString errorMessage;
532             files = generateFiles(wizard.data(), &errorMessage);
533             if (files.empty()) {
534                 QMessageBox::critical(0, tr("File Generation Failure"), errorMessage);
535                 break;
536             }
537         }
538         if (firstExtensionPageHit)
539             foreach (IFileWizardExtension *ex, extensions)
540                 ex->firstExtensionPageShown(files);
541         if (accepted)
542             break;
543     }
544     if (files.empty())
545         return;
546     // Compile result list and prompt for overwrite
547     QStringList result;
548     foreach (const GeneratedFile &generatedFile, files)
549         result.push_back(generatedFile.path());
550
551     switch (promptOverwrite(result, &errorMessage)) {
552     case OverwriteCanceled:
553         return;
554     case OverwriteError:
555         QMessageBox::critical(0, tr("Existing files"), errorMessage);
556         return;
557     case OverwriteOk:
558         break;
559     }
560
561     // Write
562     if (!writeFiles(files, &errorMessage)) {
563         QMessageBox::critical(parent, tr("File Generation Failure"), errorMessage);
564         return;
565     }
566
567     bool removeOpenProjectAttribute = false;
568     // Run the extensions
569     foreach (IFileWizardExtension *ex, extensions) {
570         bool remove;
571         if (!ex->process(files, &remove, &errorMessage)) {
572             QMessageBox::critical(parent, tr("File Generation Failure"), errorMessage);
573             return;
574         }
575         removeOpenProjectAttribute |= remove;
576     }
577
578     if (removeOpenProjectAttribute) {
579         for (int i = 0; i < files.count(); i++) {
580             if (files[i].attributes() & Core::GeneratedFile::OpenProjectAttribute)
581                 files[i].setAttributes(Core::GeneratedFile::OpenEditorAttribute);
582         }
583     }
584
585     // Post generation handler
586     if (!postGenerateFiles(wizard.data(), files, &errorMessage))
587         QMessageBox::critical(0, tr("File Generation Failure"), errorMessage);
588 }
589
590 // Write
591 bool BaseFileWizard::writeFiles(const GeneratedFiles &files, QString *errorMessage)
592 {
593     foreach (const GeneratedFile &generatedFile, files)
594         if (!(generatedFile.attributes() & GeneratedFile::CustomGeneratorAttribute))
595             if (!generatedFile.write(errorMessage))
596                 return false;
597     return true;
598 }
599
600
601 void BaseFileWizard::setupWizard(QWizard *w)
602 {
603     w->setOption(QWizard::NoCancelButton, false);
604     w->setOption(QWizard::NoDefaultButton, false);
605     w->setOption(QWizard::NoBackButtonOnStartPage, true);
606 }
607
608 void BaseFileWizard::applyExtensionPageShortTitle(Utils::Wizard *wizard, int pageId)
609 {
610     if (pageId < 0)
611         return;
612     QWizardPage *p = wizard->page(pageId);
613     if (!p)
614         return;
615     Utils::WizardProgressItem *item = wizard->wizardProgress()->item(pageId);
616     if (!item)
617         return;
618     const QString shortTitle = p->property("shortTitle").toString();
619     if (!shortTitle.isEmpty())
620       item->setTitle(shortTitle);
621 }
622
623 bool BaseFileWizard::postGenerateFiles(const QWizard *, const GeneratedFiles &l, QString *errorMessage)
624 {
625     return BaseFileWizard::postGenerateOpenEditors(l, errorMessage);
626 }
627
628 bool BaseFileWizard::postGenerateOpenEditors(const GeneratedFiles &l, QString *errorMessage)
629 {
630     Core::EditorManager *em = Core::EditorManager::instance();
631     foreach(const Core::GeneratedFile &file, l) {
632         if (file.attributes() & Core::GeneratedFile::OpenEditorAttribute) {
633             if (!em->openEditor(file.path(), file.editorId(), Core::EditorManager::ModeSwitch )) {
634                 if (errorMessage)
635                     *errorMessage = tr("Failed to open an editor for '%1'.").arg(QDir::toNativeSeparators(file.path()));
636                 return false;
637             }
638         }
639     }
640     return true;
641 }
642
643 BaseFileWizard::OverwriteResult BaseFileWizard::promptOverwrite(const QStringList &files,
644                                                                 QString *errorMessage) const
645 {
646     if (debugWizard)
647         qDebug() << Q_FUNC_INFO << files;
648
649     QStringList existingFiles;
650     bool oddStuffFound = false;
651
652     static const QString readOnlyMsg = tr(" [read only]");
653     static const QString directoryMsg = tr(" [directory]");
654     static const QString symLinkMsg = tr(" [symbolic link]");
655
656     foreach (const QString &fileName, files) {
657         const QFileInfo fi(fileName);
658         if (fi.exists())
659             existingFiles.append(fileName);
660     }
661     // Note: Generated files are using native separators, no need to convert.
662     const QString commonExistingPath = Utils::commonPath(existingFiles);
663     // Format a file list message as ( "<file1> [readonly], <file2> [directory]").
664     QString fileNamesMsgPart;
665     foreach (const QString &fileName, existingFiles) {
666         const QFileInfo fi(fileName);
667         if (fi.exists()) {
668             if (!fileNamesMsgPart.isEmpty())
669                 fileNamesMsgPart += QLatin1String(", ");
670             fileNamesMsgPart += QDir::toNativeSeparators(fileName.mid(commonExistingPath.size() + 1));
671             do {
672                 if (fi.isDir()) {
673                     oddStuffFound = true;
674                     fileNamesMsgPart += directoryMsg;
675                     break;
676                 }
677                 if (fi.isSymLink()) {
678                     oddStuffFound = true;
679                     fileNamesMsgPart += symLinkMsg;
680                     break;
681             }
682                 if (!fi.isWritable()) {
683                     oddStuffFound = true;
684                     fileNamesMsgPart += readOnlyMsg;
685                 }
686             } while (false);
687         }
688     }
689
690     if (existingFiles.isEmpty())
691         return OverwriteOk;
692
693     if (oddStuffFound) {
694         *errorMessage = tr("The project directory %1 contains files which cannot be overwritten:\n%2.")
695                 .arg(QDir::toNativeSeparators(commonExistingPath)).arg(fileNamesMsgPart);
696         return OverwriteError;
697     }
698
699     const QString messageFormat = tr("The following files already exist in the directory %1:\n"
700                                      "%2.\nWould you like to overwrite them?");
701     const QString message = messageFormat.arg(QDir::toNativeSeparators(commonExistingPath)).arg(fileNamesMsgPart);
702     const bool yes = (QMessageBox::question(Core::ICore::instance()->mainWindow(),
703                                             tr("Existing files"), message,
704                                             QMessageBox::Yes | QMessageBox::No,
705                                             QMessageBox::No)
706                       == QMessageBox::Yes);
707     return yes ? OverwriteOk :  OverwriteCanceled;
708 }
709
710 QString BaseFileWizard::buildFileName(const QString &path,
711                                       const QString &baseName,
712                                       const QString &extension)
713 {
714     QString rc = path;
715     if (!rc.isEmpty() && !rc.endsWith(QDir::separator()))
716         rc += QDir::separator();
717     rc += baseName;
718     // Add extension unless user specified something else
719     const QChar dot = QLatin1Char('.');
720     if (!extension.isEmpty() && !baseName.contains(dot)) {
721         if (!extension.startsWith(dot))
722             rc += dot;
723         rc += extension;
724     }
725     if (debugWizard)
726         qDebug() << Q_FUNC_INFO << rc;
727     return rc;
728 }
729
730 QString BaseFileWizard::preferredSuffix(const QString &mimeType)
731 {
732     const QString rc = Core::ICore::instance()->mimeDatabase()->preferredSuffixByType(mimeType);
733     if (rc.isEmpty())
734         qWarning("%s: WARNING: Unable to find a preferred suffix for %s.",
735                  Q_FUNC_INFO, mimeType.toUtf8().constData());
736     return rc;
737 }
738
739 // ------------- StandardFileWizard
740
741 StandardFileWizard::StandardFileWizard(const BaseFileWizardParameters &parameters,
742                                        QObject *parent) :
743     BaseFileWizard(parameters, parent)
744 {
745 }
746
747 QWizard *StandardFileWizard::createWizardDialog(QWidget *parent,
748                                                 const QString &defaultPath,
749                                                 const WizardPageList &extensionPages) const
750 {
751     Utils::FileWizardDialog *standardWizardDialog = new Utils::FileWizardDialog(parent);
752     standardWizardDialog->setWindowTitle(tr("New %1").arg(displayName()));
753     setupWizard(standardWizardDialog);
754     standardWizardDialog->setPath(defaultPath);
755     foreach (QWizardPage *p, extensionPages)
756         BaseFileWizard::applyExtensionPageShortTitle(standardWizardDialog, standardWizardDialog->addPage(p));
757     return standardWizardDialog;
758 }
759
760 GeneratedFiles StandardFileWizard::generateFiles(const QWizard *w,
761                                                  QString *errorMessage) const
762 {
763     const Utils::FileWizardDialog *standardWizardDialog = qobject_cast<const Utils::FileWizardDialog *>(w);
764     return generateFilesFromPath(standardWizardDialog->path(),
765                                  standardWizardDialog->fileName(),
766                                  errorMessage);
767 }
768
769 } // namespace Core
770
771 #include "basefilewizard.moc"