Commit 3e34a9ae authored by Friedemann Kleint's avatar Friedemann Kleint
Browse files

Project Wizards: Introduce notion of project directory, polish.



- Introduce project directory and "use" flag to file manager, use that
  in new item dialog
- Add configuration under Project settings, rename it to "General"
- Make wizards create project names as "untitled1.."
- Remove modules page from Qt application wizards (parametrizable)
- Give Utils::ProjectIntroPage a "Set as default location" toggle.
- Introduce wizard dialog base classes for handling that.
- Introduce notion of "last visited directory to file manager" for
  open and non-project wizards, route open through file manager.
- Clean out QmlAppWizard

Task-number: QTCREATORBUG-333
Rubber-stamped-by: default avatarcon <qtc-committer@nokia.com>
parent f27c5cc6
......@@ -208,4 +208,14 @@ void ProjectIntroPage::hideStatusLabel()
displayStatusMessage(Hint, QString());
}
bool ProjectIntroPage::useAsDefaultPath() const
{
return m_d->m_ui.projectsDirectoryCheckBox->isChecked();
}
void ProjectIntroPage::setUseAsDefaultPath(bool u)
{
m_d->m_ui.projectsDirectoryCheckBox->setChecked(u);
}
} // namespace Utils
......@@ -58,6 +58,7 @@ class QTCREATOR_UTILS_EXPORT ProjectIntroPage : public QWizardPage
Q_PROPERTY(QString description READ description WRITE setPath DESIGNABLE true)
Q_PROPERTY(QString path READ path WRITE setPath DESIGNABLE true)
Q_PROPERTY(QString name READ name WRITE setName DESIGNABLE true)
Q_PROPERTY(bool useAsDefaultPath READ useAsDefaultPath WRITE setUseAsDefaultPath DESIGNABLE true)
public:
explicit ProjectIntroPage(QWidget *parent = 0);
virtual ~ProjectIntroPage();
......@@ -65,11 +66,12 @@ public:
QString name() const;
QString path() const;
QString description() const;
bool useAsDefaultPath() const;
// Insert an additional control into the form layout for the target.
void insertControl(int row, QWidget *label, QWidget *control);
virtual bool isComplete() const;
virtual bool isComplete() const;
// Validate a project directory name entry field
static bool validateProjectDirectory(const QString &name, QString *errorMessage);
......@@ -81,6 +83,7 @@ public slots:
void setPath(const QString &path);
void setName(const QString &name);
void setDescription(const QString &description);
void setUseAsDefaultPath(bool u);
private slots:
void slotChanged();
......
......@@ -2,14 +2,6 @@
<ui version="4.0">
<class>Utils::ProjectIntroPage</class>
<widget class="QWizardPage" name="Utils::ProjectIntroPage">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>208</width>
<height>143</height>
</rect>
</property>
<property name="title">
<string>Introduction and project location</string>
</property>
......@@ -41,53 +33,59 @@
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="nameLabel">
<property name="text">
<string>Name:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="Utils::ProjectNameValidatingLineEdit" name="nameLineEdit"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="pathLabel">
<property name="text">
<string>Create in:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="Utils::PathChooser" name="pathChooser" native="true"/>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="nameLabel">
<property name="text">
<string>Name:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="Utils::ProjectNameValidatingLineEdit" name="nameLineEdit"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="pathLabel">
<property name="text">
<string>Create in:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="Utils::PathChooser" name="pathChooser"/>
</item>
<item row="1" column="0">
<spacer name="directorySeparatorLabel">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>12</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="0" colspan="2">
<widget class="QCheckBox" name="projectsDirectoryCheckBox">
<property name="text">
<string>Use as default project location</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QLabel" name="stateLabel">
......@@ -99,17 +97,17 @@
</layout>
</widget>
<customwidgets>
<customwidget>
<class>Utils::ProjectNameValidatingLineEdit</class>
<extends>QLineEdit</extends>
<header location="global">utils/projectnamevalidatinglineedit.h</header>
</customwidget>
<customwidget>
<class>Utils::PathChooser</class>
<extends>QWidget</extends>
<header>pathchooser.h</header>
<header location="global">utils/pathchooser.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>Utils::ProjectNameValidatingLineEdit</class>
<extends>QLineEdit</extends>
<header>projectnamevalidatinglineedit.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
......
......@@ -37,6 +37,7 @@
#include <extensionsystem/pluginmanager.h>
#include <utils/filewizarddialog.h>
#include <utils/qtcassert.h>
#include <QtCore/QDir>
#include <QtCore/QFile>
......@@ -423,6 +424,8 @@ QString BaseFileWizard::trCategory() const
QStringList BaseFileWizard::runWizard(const QString &path, QWidget *parent)
{
QTC_ASSERT(!path.isEmpty(), return QStringList())
typedef QList<IFileWizardExtension*> ExtensionList;
QString errorMessage;
......
......@@ -1166,21 +1166,10 @@ bool EditorManager::openExternalEditor(const QString &fileName, const QString &e
QStringList EditorManager::getOpenFileNames() const
{
static QString dir = QDir::homePath();
if (m_d->fileFilters.isEmpty())
m_d->fileFilters = formatFileFilters(m_d->m_core, &m_d->selectedFilter);
QString currentFile = ICore::instance()->fileManager()->currentFile();
if (!currentFile.isEmpty()) {
const QFileInfo fi(currentFile);
dir = fi.absolutePath();
}
QStringList files = QFileDialog::getOpenFileNames(m_d->m_core->mainWindow(), tr("Open File"),
dir, m_d->fileFilters, &m_d->selectedFilter);
if (!files.isEmpty())
dir = QFileInfo(files.at(0)).absolutePath();
return files;
return ICore::instance()->fileManager()->getOpenFileNames(m_d->fileFilters,
QString(), &m_d->selectedFilter);
}
void EditorManager::ensureEditorManagerVisible()
......
......@@ -39,6 +39,7 @@
#include "vcsmanager.h"
#include <utils/qtcassert.h>
#include <utils/pathchooser.h>
#include <QtCore/QDebug>
#include <QtCore/QSettings>
......@@ -77,8 +78,12 @@
(see addToRecentFiles() and recentFiles()).
*/
static const char *settingsGroup = "RecentFiles";
static const char *filesKey = "Files";
static const char settingsGroupC[] = "RecentFiles";
static const char filesKeyC[] = "Files";
static const char directoryGroupC[] = "Directories";
static const char projectDirectoryKeyC[] = "Projects";
static const char useProjectDirectoryKeyC[] = "UseProjectsDirectory";
namespace Core {
namespace Internal {
......@@ -104,12 +109,22 @@ struct FileManagerPrivate {
QFileSystemWatcher *m_fileWatcher;
QList<QPointer<IFile> > m_changedFiles;
bool m_blockActivated;
QString m_lastVisitedDirectory;
QString m_projectsDirectory;
bool m_useProjectsDirectory;
};
FileManagerPrivate::FileManagerPrivate(QObject *q, QMainWindow *mw) :
m_mainWindow(mw),
m_fileWatcher(new QFileSystemWatcher(q)),
m_blockActivated(false)
m_blockActivated(false),
m_lastVisitedDirectory(QDir::currentPath()),
m_projectsDirectory(Utils::PathChooser::homePath()),
#ifdef Q_OS_MAC // Creator is in bizarre places when launched via finder.
m_useProjectsDirectory(true)
#else
m_useProjectsDirectory(false)
#endif
{
}
......@@ -128,7 +143,7 @@ FileManager::FileManager(QMainWindow *mw)
this, SLOT(syncWithEditor(Core::IContext*)));
const QSettings *s = core->settings();
d->m_recentFiles = s->value(QLatin1String(settingsGroup) + QLatin1Char('/') + QLatin1String(filesKey), QStringList()).toStringList();
d->m_recentFiles = s->value(QLatin1String(settingsGroupC) + QLatin1Char('/') + QLatin1String(filesKeyC), QStringList()).toStringList();
for (QStringList::iterator it = d->m_recentFiles.begin(); it != d->m_recentFiles.end(); ) {
if (QFileInfo(*it).isFile()) {
++it;
......@@ -136,6 +151,10 @@ FileManager::FileManager(QMainWindow *mw)
it = d->m_recentFiles.erase(it);
}
}
const QString directoryGroup = QLatin1String(directoryGroupC) + QLatin1Char('/');
d->m_projectsDirectory = s->value(directoryGroup + QLatin1String(projectDirectoryKeyC), QString()).toString();
d->m_useProjectsDirectory = s->value(directoryGroup + QLatin1String(useProjectDirectoryKeyC),
d->m_useProjectsDirectory).toBool();
}
FileManager::~FileManager()
......@@ -441,13 +460,14 @@ QList<IFile *> FileManager::saveModifiedFiles(const QList<IFile *> &files,
return notSaved;
}
QString FileManager::getSaveFileNameWithExtension(const QString &title, const QString &path,
QString FileManager::getSaveFileNameWithExtension(const QString &title, const QString &pathIn,
const QString &fileFilter, const QString &extension)
{
QString fileName;
bool repeat;
do {
repeat = false;
const QString path = pathIn.isEmpty() ? fileDialogInitialDirectory() : pathIn;
fileName = QFileDialog::getSaveFileName(d->m_mainWindow, title, path, fileFilter);
if (!fileName.isEmpty() && !extension.isEmpty() && !fileName.endsWith(extension)) {
fileName.append(extension);
......@@ -459,6 +479,8 @@ QString FileManager::getSaveFileNameWithExtension(const QString &title, const QS
}
}
} while (repeat);
if (!fileName.isEmpty())
setFileDialogLastVisitedDirectory(QFileInfo(fileName).absolutePath());
return fileName;
}
......@@ -495,6 +517,27 @@ QString FileManager::getSaveAsFileName(IFile *file)
return absoluteFilePath;
}
/*!
\fn QString FileManager::getOpenFileNames(const QStringList &filters, QString *selectedFilter) const
Asks the user for a set of file names to be opened.
*/
QStringList FileManager::getOpenFileNames(const QString &filters,
const QString pathIn,
QString *selectedFilter)
{
const QString path = pathIn.isEmpty() ? fileDialogInitialDirectory() : pathIn;
const QStringList files = QFileDialog::getOpenFileNames(d->m_mainWindow,
tr("Open File"),
path, filters,
selectedFilter);
if (!files.isEmpty())
setFileDialogLastVisitedDirectory(QFileInfo(files.front()).absolutePath());
return files;
}
void FileManager::changedFile(const QString &file)
{
const bool wasempty = d->m_changedFiles.isEmpty();
......@@ -586,8 +629,12 @@ QStringList FileManager::recentFiles() const
void FileManager::saveRecentFiles()
{
QSettings *s = Core::ICore::instance()->settings();
s->beginGroup(QLatin1String(settingsGroup));
s->setValue(QLatin1String(filesKey), d->m_recentFiles);
s->beginGroup(QLatin1String(settingsGroupC));
s->setValue(QLatin1String(filesKeyC), d->m_recentFiles);
s->endGroup();
s->beginGroup(QLatin1String(directoryGroupC));
s->setValue(QLatin1String(projectDirectoryKeyC), d->m_projectsDirectory);
s->setValue(QLatin1String(useProjectDirectoryKeyC), d->m_useProjectsDirectory);
s->endGroup();
}
......@@ -638,6 +685,99 @@ QList<IFile *> FileManager::managedFiles(const QString &fileName) const
return result;
}
/*!
Returns the initial directory for a new file dialog. If there is
a current file, use that, else use last visited directory.
\sa setFileDialogLastVisitedDirectory
*/
QString FileManager::fileDialogInitialDirectory() const
{
if (!d->m_currentFile.isEmpty())
return QFileInfo(d->m_currentFile).absolutePath();
return d->m_lastVisitedDirectory;
}
/*!
Returns the directory for projects. Defaults to HOME.
\sa setProjectsDirectory, setUseProjectsDirectory
*/
QString FileManager::projectsDirectory() const
{
return d->m_projectsDirectory;
}
/*!
Set the directory for projects.
\sa projectsDirectory, useProjectsDirectory
*/
void FileManager::setProjectsDirectory(const QString &dir)
{
d->m_projectsDirectory = dir;
}
/*!
Returns whether the directory for projects is to be
used or the user wants the current directory.
\sa setProjectsDirectory, setUseProjectsDirectory
*/
bool FileManager::useProjectsDirectory() const
{
return d->m_useProjectsDirectory;
}
/*!
Sets whether the directory for projects is to be used.
\sa projectsDirectory, useProjectsDirectory
*/
void FileManager::setUseProjectsDirectory(bool useProjectsDirectory)
{
d->m_useProjectsDirectory = useProjectsDirectory;
}
/*!
Returns last visited directory of a file dialog.
\sa setFileDialogLastVisitedDirectory, fileDialogInitialDirectory
*/
QString FileManager::fileDialogLastVisitedDirectory() const
{
return d->m_lastVisitedDirectory;
}
/*!
Set the last visited directory of a file dialog that will be remembered
for the next one.
\sa fileDialogLastVisitedDirectory, fileDialogInitialDirectory
*/
void FileManager::setFileDialogLastVisitedDirectory(const QString &directory)
{
d->m_lastVisitedDirectory = directory;
}
// -------------- FileChangeBlocker
FileChangeBlocker::FileChangeBlocker(const QString &fileName)
: m_reload(false)
{
......
......@@ -79,6 +79,10 @@ public:
// helper methods
static QString fixFileName(const QString &fileName);
QStringList getOpenFileNames(const QString &filters,
const QString path = QString(),
QString *selectedFilter = 0);
QString getSaveFileNameWithExtension(const QString &title, const QString &path,
const QString &fileFilter, const QString &extension);
QString getSaveAsFileName(IFile *file);
......@@ -90,6 +94,18 @@ public:
const QString &alwaysSaveMessage = QString::null,
bool *alwaysSave = 0);
QString fileDialogLastVisitedDirectory() const;
void setFileDialogLastVisitedDirectory(const QString &);
QString fileDialogInitialDirectory() const;
bool useProjectsDirectory() const;
void setUseProjectsDirectory(bool);
QString projectsDirectory() const;
void setProjectsDirectory(const QString &);
signals:
void currentFileChanged(const QString &filePath);
......
......@@ -866,12 +866,6 @@ QStringList MainWindow::showNewItemDialog(const QString &title,
const QList<IWizard *> &wizards,
const QString &defaultLocation)
{
QString defaultDir = defaultLocation;
if (defaultDir.isEmpty() && !m_coreImpl->fileManager()->currentFile().isEmpty())
defaultDir = QFileInfo(m_coreImpl->fileManager()->currentFile()).absolutePath();
if (defaultDir.isEmpty())
defaultDir = Utils::PathChooser::homePath();
// Scan for wizards matching the filter and pick one. Don't show
// dialog if there is only one.
IWizard *wizard = 0;
......@@ -892,7 +886,25 @@ QStringList MainWindow::showNewItemDialog(const QString &title,
if (!wizard)
return QStringList();
return wizard->runWizard(defaultDir, this);
QString path = defaultLocation;
if (path.isEmpty()) {
const FileManager *fm = m_coreImpl->fileManager();
switch (wizard->kind()) {
case IWizard::ProjectWizard:
// Project wizards: Check for projects directory or
// use last visited directory of file dialog. Never start
// at current.
path = fm->useProjectsDirectory() ?
fm->projectsDirectory() :
fm->fileDialogLastVisitedDirectory();
break;
default:
path = fm->fileDialogInitialDirectory();
break;
}
}
return wizard->runWizard(path, this);
}
bool MainWindow::showOptionsDialog(const QString &category,
......
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
**
**************************************************************************/
#include "baseprojectwizarddialog.h"
#include <coreplugin/basefilewizard.h>
#include <coreplugin/icore.h>
#include <coreplugin/filemanager.h>
#include <utils/projectintropage.h>
#include <QtCore/QDir>
namespace ProjectExplorer {
struct BaseProjectWizardDialogPrivate {
explicit BaseProjectWizardDialogPrivate(Utils::ProjectIntroPage *page, int id = -1);
const int introId;
Utils::ProjectIntroPage *introPage;
};
BaseProjectWizardDialogPrivate::BaseProjectWizardDialogPrivate(Utils::ProjectIntroPage *page, int id) :
introId(id),
introPage(page)
{
}
BaseProjectWizardDialog::BaseProjectWizardDialog(QWidget *parent) :
QWizard(parent),
d(new BaseProjectWizardDialogPrivate(new Utils::ProjectIntroPage))
{
init();
}
BaseProjectWizardDialog::BaseProjectWizardDialog(Utils::ProjectIntroPage *introPage,
int introId,
QWidget *parent) :
QWizard(parent),
d(new BaseProjectWizardDialogPrivate(introPage, introId))
{
init();
}
void BaseProjectWizardDialog::init()
{