2012-10-02 09:12:39 +02:00
|
|
|
/****************************************************************************
|
2008-12-02 12:01:29 +01:00
|
|
|
**
|
2015-01-14 18:07:15 +01:00
|
|
|
** Copyright (C) 2015 The Qt Company Ltd.
|
|
|
|
|
** Contact: http://www.qt.io/licensing
|
2008-12-02 12:01:29 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** This file is part of Qt Creator.
|
2008-12-02 12:01:29 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** 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
|
2015-01-14 18:07:15 +01:00
|
|
|
** a written agreement between you and The Qt Company. For licensing terms and
|
|
|
|
|
** conditions see http://www.qt.io/terms-conditions. For further information
|
2014-10-01 13:21:18 +02:00
|
|
|
** use the contact form at http://www.qt.io/contact-us.
|
2008-12-02 14:17:16 +01:00
|
|
|
**
|
2009-02-25 09:15:00 +01:00
|
|
|
** GNU Lesser General Public License Usage
|
2012-10-02 09:12:39 +02:00
|
|
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
2014-10-01 13:21:18 +02:00
|
|
|
** 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.
|
2012-10-02 09:12:39 +02:00
|
|
|
**
|
2015-01-14 18:07:15 +01:00
|
|
|
** In addition, as a special exception, The Qt Company gives you certain additional
|
|
|
|
|
** rights. These rights are described in The Qt Company LGPL Exception
|
2010-12-17 16:01:08 +01:00
|
|
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
****************************************************************************/
|
2008-12-02 14:09:21 +01:00
|
|
|
|
2014-05-26 16:58:50 +02:00
|
|
|
#include "basefilewizardfactory.h"
|
2014-05-27 13:18:05 +02:00
|
|
|
|
|
|
|
|
#include "basefilewizard.h"
|
2015-01-05 11:12:39 +01:00
|
|
|
#include "icontext.h"
|
2009-01-23 13:03:36 +01:00
|
|
|
#include "icore.h"
|
|
|
|
|
#include "ifilewizardextension.h"
|
2008-12-02 12:01:29 +01:00
|
|
|
#include "mimedatabase.h"
|
2009-01-23 13:03:36 +01:00
|
|
|
#include "editormanager/editormanager.h"
|
2011-04-15 11:27:15 +02:00
|
|
|
#include "dialogs/promptoverwritedialog.h"
|
2009-01-19 12:39:20 +01:00
|
|
|
#include <extensionsystem/pluginmanager.h>
|
2014-06-02 14:01:46 +02:00
|
|
|
#include <utils/filewizardpage.h>
|
|
|
|
|
#include <utils/wizard.h>
|
2009-11-26 18:03:16 +01:00
|
|
|
#include <utils/qtcassert.h>
|
2010-06-08 17:33:37 +02:00
|
|
|
#include <utils/stringutils.h>
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QDir>
|
|
|
|
|
#include <QFileInfo>
|
|
|
|
|
#include <QDebug>
|
|
|
|
|
#include <QSharedData>
|
|
|
|
|
#include <QEventLoop>
|
|
|
|
|
#include <QScopedPointer>
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QMessageBox>
|
|
|
|
|
#include <QWizard>
|
|
|
|
|
#include <QIcon>
|
2008-12-02 12:01:29 +01:00
|
|
|
|
|
|
|
|
enum { debugWizard = 0 };
|
|
|
|
|
|
|
|
|
|
namespace Core {
|
|
|
|
|
|
2011-04-15 11:27:15 +02:00
|
|
|
static int indexOfFile(const GeneratedFiles &f, const QString &path)
|
|
|
|
|
{
|
|
|
|
|
const int size = f.size();
|
|
|
|
|
for (int i = 0; i < size; ++i)
|
|
|
|
|
if (f.at(i).path() == path)
|
|
|
|
|
return i;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-01 12:18:25 +02:00
|
|
|
/*!
|
|
|
|
|
\class Core::Internal::WizardEventLoop
|
2013-09-06 16:38:53 +02:00
|
|
|
\brief The WizardEventLoop class implements a special event
|
|
|
|
|
loop that runs a QWizard and terminates if the page changes.
|
2011-04-01 12:18:25 +02:00
|
|
|
|
2013-09-06 16:38:53 +02:00
|
|
|
Used by Core::BaseFileWizard to intercept the change from the standard wizard pages
|
2011-04-01 12:18:25 +02:00
|
|
|
to the extension pages (as the latter require the list of Core::GeneratedFile generated).
|
|
|
|
|
|
|
|
|
|
Synopsis:
|
|
|
|
|
\code
|
2008-12-02 12:01:29 +01:00
|
|
|
Wizard wizard(parent);
|
|
|
|
|
WizardEventLoop::WizardResult wr;
|
|
|
|
|
do {
|
|
|
|
|
wr = WizardEventLoop::execWizardPage(wizard);
|
|
|
|
|
} while (wr == WizardEventLoop::PageChanged);
|
2011-04-01 12:18:25 +02:00
|
|
|
\endcode
|
|
|
|
|
|
|
|
|
|
\sa Core::GeneratedFile, Core::BaseFileWizardParameters, Core::BaseFileWizard, Core::StandardFileWizard
|
|
|
|
|
*/
|
2008-12-02 12:01:29 +01:00
|
|
|
|
|
|
|
|
class WizardEventLoop : public QEventLoop
|
|
|
|
|
{
|
|
|
|
|
Q_OBJECT
|
|
|
|
|
WizardEventLoop(QObject *parent);
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
enum WizardResult { Accepted, Rejected , PageChanged };
|
|
|
|
|
|
|
|
|
|
static WizardResult execWizardPage(QWizard &w);
|
|
|
|
|
|
|
|
|
|
private slots:
|
|
|
|
|
void pageChanged(int);
|
|
|
|
|
void accepted();
|
|
|
|
|
void rejected();
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
WizardResult execWizardPageI();
|
|
|
|
|
|
|
|
|
|
WizardResult m_result;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
WizardEventLoop::WizardEventLoop(QObject *parent) :
|
|
|
|
|
QEventLoop(parent),
|
|
|
|
|
m_result(Rejected)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WizardEventLoop::WizardResult WizardEventLoop::execWizardPage(QWizard &wizard)
|
|
|
|
|
{
|
|
|
|
|
/* Install ourselves on the wizard. Main trick is here to connect
|
|
|
|
|
* to the page changed signal and quit() on it. */
|
|
|
|
|
WizardEventLoop *eventLoop = wizard.findChild<WizardEventLoop *>();
|
|
|
|
|
if (!eventLoop) {
|
|
|
|
|
eventLoop = new WizardEventLoop(&wizard);
|
|
|
|
|
connect(&wizard, SIGNAL(currentIdChanged(int)), eventLoop, SLOT(pageChanged(int)));
|
|
|
|
|
connect(&wizard, SIGNAL(accepted()), eventLoop, SLOT(accepted()));
|
|
|
|
|
connect(&wizard, SIGNAL(rejected()), eventLoop, SLOT(rejected()));
|
2014-07-16 10:42:40 +02:00
|
|
|
wizard.setWindowFlags(wizard.windowFlags());
|
2008-12-02 12:01:29 +01:00
|
|
|
wizard.show();
|
|
|
|
|
}
|
|
|
|
|
const WizardResult result = eventLoop->execWizardPageI();
|
|
|
|
|
// Quitting?
|
|
|
|
|
if (result != PageChanged)
|
|
|
|
|
delete eventLoop;
|
|
|
|
|
if (debugWizard)
|
|
|
|
|
qDebug() << "WizardEventLoop::runWizard" << wizard.pageIds() << " returns " << result;
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WizardEventLoop::WizardResult WizardEventLoop::execWizardPageI()
|
|
|
|
|
{
|
|
|
|
|
m_result = Rejected;
|
2014-06-27 15:15:09 +02:00
|
|
|
exec();
|
2008-12-02 12:01:29 +01:00
|
|
|
return m_result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WizardEventLoop::pageChanged(int /*page*/)
|
|
|
|
|
{
|
|
|
|
|
m_result = PageChanged;
|
|
|
|
|
quit(); // !
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WizardEventLoop::accepted()
|
|
|
|
|
{
|
|
|
|
|
m_result = Accepted;
|
|
|
|
|
quit();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WizardEventLoop::rejected()
|
|
|
|
|
{
|
|
|
|
|
m_result = Rejected;
|
|
|
|
|
quit();
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-01 12:18:25 +02:00
|
|
|
/*!
|
|
|
|
|
\class Core::BaseFileWizard
|
2013-06-05 14:29:24 +02:00
|
|
|
\brief The BaseFileWizard class implements a generic wizard for
|
|
|
|
|
creating files.
|
2011-04-01 12:18:25 +02:00
|
|
|
|
2013-10-07 13:34:40 +02:00
|
|
|
The following abstract functions must be implemented:
|
2011-04-01 12:18:25 +02:00
|
|
|
\list
|
2014-05-27 12:23:38 +02:00
|
|
|
\li create(): Called to create the QWizard dialog to be shown.
|
2013-09-06 16:38:53 +02:00
|
|
|
\li generateFiles(): Generates file content.
|
2011-04-01 12:18:25 +02:00
|
|
|
\endlist
|
|
|
|
|
|
2013-10-07 13:34:40 +02:00
|
|
|
The behaviour can be further customized by overwriting the virtual function \c postGenerateFiles(),
|
2011-04-01 12:18:25 +02:00
|
|
|
which is called after generating the files.
|
|
|
|
|
|
|
|
|
|
\sa Core::GeneratedFile, Core::BaseFileWizardParameters, Core::StandardFileWizard
|
|
|
|
|
\sa Core::Internal::WizardEventLoop
|
|
|
|
|
*/
|
|
|
|
|
|
2014-05-26 16:58:50 +02:00
|
|
|
void BaseFileWizardFactory::runWizard(const QString &path, QWidget *parent, const QString &platform, const QVariantMap &extraValues)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2010-09-16 17:09:36 +02:00
|
|
|
QTC_ASSERT(!path.isEmpty(), return);
|
2009-11-26 18:03:16 +01:00
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
QString errorMessage;
|
|
|
|
|
// Compile extension pages, purge out unused ones
|
2014-05-27 14:12:36 +02:00
|
|
|
QList<IFileWizardExtension *> extensionList = ExtensionSystem::PluginManager::getObjects<IFileWizardExtension>();
|
2008-12-02 12:01:29 +01:00
|
|
|
WizardPageList allExtensionPages;
|
2014-05-27 14:12:36 +02:00
|
|
|
for (auto it = extensionList.begin(); it != extensionList.end(); ) {
|
2008-12-02 12:01:29 +01:00
|
|
|
const WizardPageList extensionPages = (*it)->extensionPages(this);
|
|
|
|
|
if (extensionPages.empty()) {
|
2014-02-14 12:59:19 +01:00
|
|
|
it = extensionList.erase(it);
|
2008-12-02 12:01:29 +01:00
|
|
|
} else {
|
|
|
|
|
allExtensionPages += extensionPages;
|
|
|
|
|
++it;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (debugWizard)
|
2014-02-14 12:59:19 +01:00
|
|
|
qDebug() << Q_FUNC_INFO << path << parent << "exs" << extensionList.size() << allExtensionPages.size();
|
2008-12-02 12:01:29 +01:00
|
|
|
|
|
|
|
|
QWizardPage *firstExtensionPage = 0;
|
|
|
|
|
if (!allExtensionPages.empty())
|
|
|
|
|
firstExtensionPage = allExtensionPages.front();
|
|
|
|
|
|
|
|
|
|
// Create dialog and run it. Ensure that the dialog is deleted when
|
|
|
|
|
// leaving the func, but not before the IFileWizardExtension::process
|
|
|
|
|
// has been called
|
2012-03-19 16:12:51 +01:00
|
|
|
|
|
|
|
|
WizardDialogParameters::DialogParameterFlags dialogParameterFlags;
|
|
|
|
|
|
|
|
|
|
if (flags().testFlag(ForceCapitalLetterForFileName))
|
|
|
|
|
dialogParameterFlags |= WizardDialogParameters::ForceCapitalLetterForFileName;
|
|
|
|
|
|
2014-05-27 12:23:38 +02:00
|
|
|
const QScopedPointer<QWizard> wizard(create(parent, WizardDialogParameters(path,
|
|
|
|
|
allExtensionPages,
|
|
|
|
|
platform,
|
|
|
|
|
requiredFeatures(),
|
|
|
|
|
dialogParameterFlags,
|
|
|
|
|
extraValues)));
|
2010-09-16 17:09:36 +02:00
|
|
|
QTC_ASSERT(!wizard.isNull(), return);
|
2015-01-05 11:12:39 +01:00
|
|
|
ICore::registerWindow(wizard.data(), Context("Core.NewWizard"));
|
2010-09-07 10:07:30 +02:00
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
GeneratedFiles files;
|
|
|
|
|
// Run the wizard: Call generate files on switching to the first extension
|
|
|
|
|
// page is OR after 'Accepted' if there are no extension pages
|
|
|
|
|
while (true) {
|
|
|
|
|
const WizardEventLoop::WizardResult wr = WizardEventLoop::execWizardPage(*wizard);
|
|
|
|
|
if (wr == WizardEventLoop::Rejected) {
|
|
|
|
|
files.clear();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
const bool accepted = wr == WizardEventLoop::Accepted;
|
|
|
|
|
const bool firstExtensionPageHit = wr == WizardEventLoop::PageChanged
|
|
|
|
|
&& wizard->page(wizard->currentId()) == firstExtensionPage;
|
|
|
|
|
const bool needGenerateFiles = firstExtensionPageHit || (accepted && allExtensionPages.empty());
|
|
|
|
|
if (needGenerateFiles) {
|
|
|
|
|
QString errorMessage;
|
|
|
|
|
files = generateFiles(wizard.data(), &errorMessage);
|
|
|
|
|
if (files.empty()) {
|
|
|
|
|
QMessageBox::critical(0, tr("File Generation Failure"), errorMessage);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (firstExtensionPageHit)
|
2014-02-14 12:59:19 +01:00
|
|
|
foreach (IFileWizardExtension *ex, extensionList)
|
2012-04-02 14:55:56 +02:00
|
|
|
ex->firstExtensionPageShown(files, extraValues);
|
2008-12-02 12:01:29 +01:00
|
|
|
if (accepted)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (files.empty())
|
2010-09-16 17:09:36 +02:00
|
|
|
return;
|
2008-12-02 12:01:29 +01:00
|
|
|
// Compile result list and prompt for overwrite
|
2011-04-15 11:27:15 +02:00
|
|
|
switch (promptOverwrite(&files, &errorMessage)) {
|
2008-12-02 12:01:29 +01:00
|
|
|
case OverwriteCanceled:
|
2010-09-16 17:09:36 +02:00
|
|
|
return;
|
2008-12-02 12:01:29 +01:00
|
|
|
case OverwriteError:
|
|
|
|
|
QMessageBox::critical(0, tr("Existing files"), errorMessage);
|
2010-09-16 17:09:36 +02:00
|
|
|
return;
|
2008-12-02 12:01:29 +01:00
|
|
|
case OverwriteOk:
|
|
|
|
|
break;
|
|
|
|
|
}
|
2011-08-05 09:59:28 +02:00
|
|
|
|
2014-02-14 12:59:19 +01:00
|
|
|
foreach (IFileWizardExtension *ex, extensionList) {
|
2011-08-05 09:59:28 +02:00
|
|
|
for (int i = 0; i < files.count(); i++) {
|
|
|
|
|
ex->applyCodeStyle(&files[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
// Write
|
2010-09-01 13:27:24 +02:00
|
|
|
if (!writeFiles(files, &errorMessage)) {
|
|
|
|
|
QMessageBox::critical(parent, tr("File Generation Failure"), errorMessage);
|
2010-09-16 17:09:36 +02:00
|
|
|
return;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
2010-09-01 13:27:24 +02:00
|
|
|
|
2010-08-26 18:33:16 +02:00
|
|
|
bool removeOpenProjectAttribute = false;
|
2008-12-02 12:01:29 +01:00
|
|
|
// Run the extensions
|
2014-02-14 12:59:19 +01:00
|
|
|
foreach (IFileWizardExtension *ex, extensionList) {
|
2010-08-26 18:33:16 +02:00
|
|
|
bool remove;
|
2011-08-05 09:59:28 +02:00
|
|
|
if (!ex->processFiles(files, &remove, &errorMessage)) {
|
2013-03-17 16:09:01 +01:00
|
|
|
if (!errorMessage.isEmpty())
|
|
|
|
|
QMessageBox::critical(parent, tr("File Generation Failure"), errorMessage);
|
2010-09-16 17:09:36 +02:00
|
|
|
return;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
2010-08-26 18:33:16 +02:00
|
|
|
removeOpenProjectAttribute |= remove;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (removeOpenProjectAttribute) {
|
|
|
|
|
for (int i = 0; i < files.count(); i++) {
|
2013-08-30 16:38:57 +02:00
|
|
|
if (files[i].attributes() & GeneratedFile::OpenProjectAttribute)
|
|
|
|
|
files[i].setAttributes(GeneratedFile::OpenEditorAttribute);
|
2010-08-26 18:33:16 +02:00
|
|
|
}
|
|
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
|
|
|
|
|
// Post generation handler
|
2010-09-16 17:09:36 +02:00
|
|
|
if (!postGenerateFiles(wizard.data(), files, &errorMessage))
|
2012-10-10 15:26:13 +02:00
|
|
|
if (!errorMessage.isEmpty())
|
|
|
|
|
QMessageBox::critical(0, tr("File Generation Failure"), errorMessage);
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2011-04-01 12:18:25 +02:00
|
|
|
/*!
|
2014-05-27 12:23:38 +02:00
|
|
|
\fn virtual QWizard *Core::BaseFileWizard::create(QWidget *parent,
|
|
|
|
|
const WizardDialogParameters ¶meters) const
|
2013-09-06 16:38:53 +02:00
|
|
|
|
2014-05-27 12:23:38 +02:00
|
|
|
Creates the wizard on the \a parent with the \a parameters.
|
2011-04-01 12:18:25 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
\fn virtual Core::GeneratedFiles Core::BaseFileWizard::generateFiles(const QWizard *w,
|
|
|
|
|
QString *errorMessage) const = 0
|
2013-09-06 16:38:53 +02:00
|
|
|
Overwrite to query the parameters from the dialog and generate the files.
|
2011-04-01 12:18:25 +02:00
|
|
|
|
2013-09-06 16:38:53 +02:00
|
|
|
\note This does not generate physical files, but merely the list of
|
|
|
|
|
Core::GeneratedFile.
|
2011-04-01 12:18:25 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*!
|
2013-09-06 16:38:53 +02:00
|
|
|
Physically writes files.
|
2011-04-01 12:18:25 +02:00
|
|
|
|
|
|
|
|
Re-implement (calling the base implementation) to create files with CustomGeneratorAttribute set.
|
|
|
|
|
*/
|
|
|
|
|
|
2014-05-26 16:58:50 +02:00
|
|
|
bool BaseFileWizardFactory::writeFiles(const GeneratedFiles &files, QString *errorMessage)
|
2010-09-01 13:27:24 +02:00
|
|
|
{
|
2011-04-15 11:27:15 +02:00
|
|
|
const GeneratedFile::Attributes noWriteAttributes
|
|
|
|
|
= GeneratedFile::CustomGeneratorAttribute|GeneratedFile::KeepExistingFileAttribute;
|
2010-09-01 13:27:24 +02:00
|
|
|
foreach (const GeneratedFile &generatedFile, files)
|
2011-04-15 11:27:15 +02:00
|
|
|
if (!(generatedFile.attributes() & noWriteAttributes ))
|
2010-09-01 13:27:24 +02:00
|
|
|
if (!generatedFile.write(errorMessage))
|
|
|
|
|
return false;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-01 12:18:25 +02:00
|
|
|
/*!
|
2013-09-06 16:38:53 +02:00
|
|
|
Overwrite to perform steps to be done after files are actually created.
|
2011-04-01 12:18:25 +02:00
|
|
|
|
|
|
|
|
The default implementation opens editors with the newly generated files.
|
|
|
|
|
*/
|
|
|
|
|
|
2014-05-26 16:58:50 +02:00
|
|
|
bool BaseFileWizardFactory::postGenerateFiles(const QWizard *, const GeneratedFiles &l, QString *errorMessage)
|
2010-04-16 15:55:32 +02:00
|
|
|
{
|
2014-05-26 16:58:50 +02:00
|
|
|
return BaseFileWizardFactory::postGenerateOpenEditors(l, errorMessage);
|
2010-04-16 15:55:32 +02:00
|
|
|
}
|
|
|
|
|
|
2011-04-01 12:18:25 +02:00
|
|
|
/*!
|
2013-09-06 16:38:53 +02:00
|
|
|
Opens the editors for the files whose attribute is set accordingly.
|
2011-04-01 12:18:25 +02:00
|
|
|
*/
|
|
|
|
|
|
2014-05-26 16:58:50 +02:00
|
|
|
bool BaseFileWizardFactory::postGenerateOpenEditors(const GeneratedFiles &l, QString *errorMessage)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2013-08-30 16:38:57 +02:00
|
|
|
foreach (const GeneratedFile &file, l) {
|
|
|
|
|
if (file.attributes() & GeneratedFile::OpenEditorAttribute) {
|
|
|
|
|
if (!EditorManager::openEditor(file.path(), file.editorId())) {
|
2010-04-16 15:55:32 +02:00
|
|
|
if (errorMessage)
|
2014-04-17 14:09:47 +02:00
|
|
|
*errorMessage = tr("Failed to open an editor for \"%1\".").arg(QDir::toNativeSeparators(file.path()));
|
2010-04-16 15:55:32 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-01 12:18:25 +02:00
|
|
|
/*!
|
2013-09-06 16:38:53 +02:00
|
|
|
Performs an overwrite check on a set of \a files. Checks if the file exists and
|
|
|
|
|
can be overwritten at all, and then prompts the user with a summary.
|
2011-04-01 12:18:25 +02:00
|
|
|
*/
|
|
|
|
|
|
2014-05-26 16:58:50 +02:00
|
|
|
BaseFileWizardFactory::OverwriteResult BaseFileWizardFactory::promptOverwrite(GeneratedFiles *files,
|
2008-12-02 12:01:29 +01:00
|
|
|
QString *errorMessage) const
|
|
|
|
|
{
|
|
|
|
|
if (debugWizard)
|
2010-06-08 17:33:37 +02:00
|
|
|
qDebug() << Q_FUNC_INFO << files;
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2010-06-08 17:33:37 +02:00
|
|
|
QStringList existingFiles;
|
2008-12-02 12:01:29 +01:00
|
|
|
bool oddStuffFound = false;
|
|
|
|
|
|
2013-10-17 14:52:10 +02:00
|
|
|
static const QString readOnlyMsg = tr("[read only]");
|
|
|
|
|
static const QString directoryMsg = tr("[folder]");
|
|
|
|
|
static const QString symLinkMsg = tr("[symbolic link]");
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2011-04-15 11:27:15 +02:00
|
|
|
foreach (const GeneratedFile &file, *files) {
|
2014-10-24 10:28:28 +02:00
|
|
|
const QString path = file.path();
|
|
|
|
|
if (QFileInfo::exists(path))
|
|
|
|
|
existingFiles.append(path);
|
2010-06-08 17:33:37 +02:00
|
|
|
}
|
2011-04-15 11:27:15 +02:00
|
|
|
if (existingFiles.isEmpty())
|
|
|
|
|
return OverwriteOk;
|
|
|
|
|
// Before prompting to overwrite existing files, loop over files and check
|
|
|
|
|
// if there is anything blocking overwriting them (like them being links or folders).
|
|
|
|
|
// Format a file list message as ( "<file1> [readonly], <file2> [folder]").
|
2010-06-08 17:33:37 +02:00
|
|
|
const QString commonExistingPath = Utils::commonPath(existingFiles);
|
2008-12-02 12:01:29 +01:00
|
|
|
QString fileNamesMsgPart;
|
2010-06-08 17:33:37 +02:00
|
|
|
foreach (const QString &fileName, existingFiles) {
|
2008-12-02 12:01:29 +01:00
|
|
|
const QFileInfo fi(fileName);
|
|
|
|
|
if (fi.exists()) {
|
|
|
|
|
if (!fileNamesMsgPart.isEmpty())
|
|
|
|
|
fileNamesMsgPart += QLatin1String(", ");
|
2010-09-30 16:50:59 +02:00
|
|
|
fileNamesMsgPart += QDir::toNativeSeparators(fileName.mid(commonExistingPath.size() + 1));
|
2008-12-02 12:01:29 +01:00
|
|
|
do {
|
|
|
|
|
if (fi.isDir()) {
|
|
|
|
|
oddStuffFound = true;
|
2013-10-17 14:52:10 +02:00
|
|
|
fileNamesMsgPart += QLatin1Char(' ') + directoryMsg;
|
2008-12-02 12:01:29 +01:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (fi.isSymLink()) {
|
|
|
|
|
oddStuffFound = true;
|
2013-10-17 14:52:10 +02:00
|
|
|
fileNamesMsgPart += QLatin1Char(' ') + symLinkMsg;
|
2008-12-02 12:01:29 +01:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (!fi.isWritable()) {
|
|
|
|
|
oddStuffFound = true;
|
2013-10-17 14:52:10 +02:00
|
|
|
fileNamesMsgPart += QLatin1Char(' ') + readOnlyMsg;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
} while (false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (oddStuffFound) {
|
2010-09-30 16:50:59 +02:00
|
|
|
*errorMessage = tr("The project directory %1 contains files which cannot be overwritten:\n%2.")
|
|
|
|
|
.arg(QDir::toNativeSeparators(commonExistingPath)).arg(fileNamesMsgPart);
|
2008-12-02 12:01:29 +01:00
|
|
|
return OverwriteError;
|
|
|
|
|
}
|
2011-04-15 11:27:15 +02:00
|
|
|
// Prompt to overwrite existing files.
|
2014-08-25 17:28:59 +02:00
|
|
|
PromptOverwriteDialog overwriteDialog;
|
2011-04-15 11:27:15 +02:00
|
|
|
// Scripts cannot handle overwrite
|
|
|
|
|
overwriteDialog.setFiles(existingFiles);
|
|
|
|
|
foreach (const GeneratedFile &file, *files)
|
|
|
|
|
if (file.attributes() & GeneratedFile::CustomGeneratorAttribute)
|
|
|
|
|
overwriteDialog.setFileEnabled(file.path(), false);
|
|
|
|
|
if (overwriteDialog.exec() != QDialog::Accepted)
|
|
|
|
|
return OverwriteCanceled;
|
|
|
|
|
const QStringList existingFilesToKeep = overwriteDialog.uncheckedFiles();
|
|
|
|
|
if (existingFilesToKeep.size() == files->size()) // All exist & all unchecked->Cancel.
|
|
|
|
|
return OverwriteCanceled;
|
|
|
|
|
// Set 'keep' attribute in files
|
|
|
|
|
foreach (const QString &keepFile, existingFilesToKeep) {
|
|
|
|
|
const int i = indexOfFile(*files, keepFile);
|
2012-04-17 08:01:25 +02:00
|
|
|
QTC_ASSERT(i != -1, return OverwriteCanceled);
|
2011-04-15 11:27:15 +02:00
|
|
|
GeneratedFile &file = (*files)[i];
|
|
|
|
|
file.setAttributes(file.attributes() | GeneratedFile::KeepExistingFileAttribute);
|
|
|
|
|
}
|
|
|
|
|
return OverwriteOk;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2011-04-01 12:18:25 +02:00
|
|
|
/*!
|
2013-09-06 16:38:53 +02:00
|
|
|
Constructs a file name, adding the \a extension unless \a baseName already has
|
|
|
|
|
one.
|
2011-04-01 12:18:25 +02:00
|
|
|
*/
|
|
|
|
|
|
2014-05-26 16:58:50 +02:00
|
|
|
QString BaseFileWizardFactory::buildFileName(const QString &path,
|
2008-12-02 12:01:29 +01:00
|
|
|
const QString &baseName,
|
|
|
|
|
const QString &extension)
|
|
|
|
|
{
|
|
|
|
|
QString rc = path;
|
2015-01-31 22:11:59 +02:00
|
|
|
const QChar slash = QLatin1Char('/');
|
|
|
|
|
if (!rc.isEmpty() && !rc.endsWith(slash))
|
|
|
|
|
rc += slash;
|
2008-12-02 12:01:29 +01:00
|
|
|
rc += baseName;
|
|
|
|
|
// Add extension unless user specified something else
|
|
|
|
|
const QChar dot = QLatin1Char('.');
|
|
|
|
|
if (!extension.isEmpty() && !baseName.contains(dot)) {
|
|
|
|
|
if (!extension.startsWith(dot))
|
|
|
|
|
rc += dot;
|
|
|
|
|
rc += extension;
|
|
|
|
|
}
|
|
|
|
|
if (debugWizard)
|
|
|
|
|
qDebug() << Q_FUNC_INFO << rc;
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-01 12:18:25 +02:00
|
|
|
/*!
|
2013-09-06 16:38:53 +02:00
|
|
|
Returns the preferred suffix for \a mimeType.
|
2011-04-01 12:18:25 +02:00
|
|
|
*/
|
|
|
|
|
|
2014-05-26 16:58:50 +02:00
|
|
|
QString BaseFileWizardFactory::preferredSuffix(const QString &mimeType)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2013-08-30 16:38:57 +02:00
|
|
|
const QString rc = MimeDatabase::preferredSuffixByType(mimeType);
|
2008-12-02 12:01:29 +01:00
|
|
|
if (rc.isEmpty())
|
|
|
|
|
qWarning("%s: WARNING: Unable to find a preferred suffix for %s.",
|
|
|
|
|
Q_FUNC_INFO, mimeType.toUtf8().constData());
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-01 12:18:25 +02:00
|
|
|
/*!
|
|
|
|
|
\class Core::StandardFileWizard
|
2013-06-05 14:29:24 +02:00
|
|
|
\brief The StandardFileWizard class is a convenience class for
|
|
|
|
|
creating one file.
|
2011-04-01 12:18:25 +02:00
|
|
|
|
|
|
|
|
It uses Utils::FileWizardDialog and introduces a new virtual to generate the
|
|
|
|
|
files from path and name.
|
|
|
|
|
|
|
|
|
|
\sa Core::GeneratedFile, Core::BaseFileWizardParameters, Core::BaseFileWizard
|
|
|
|
|
\sa Core::Internal::WizardEventLoop
|
|
|
|
|
*/
|
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
} // namespace Core
|
2008-12-02 14:09:21 +01:00
|
|
|
|
2014-05-26 16:58:50 +02:00
|
|
|
#include "basefilewizardfactory.moc"
|