Commit 4829418b authored by dt's avatar dt
Browse files

Merge commit 'origin/master'

parents b9b262f1 361a70ab
/**************************************************************************
**
/**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
......@@ -51,6 +50,7 @@
#include <Lexer.h>
#include <Token.h>
#include <Literals.h>
#include <cctype>
#include <QtDebug>
#include <algorithm>
......
......@@ -39,7 +39,8 @@ namespace Utils {
struct BaseValidatingLineEditPrivate;
/* Base class for validating line edits that performs validation in a virtual
/**
* Base class for validating line edits that performs validation in a virtual
* validate() function to be implemented in derived classes.
* When invalid, the text color will turn red and a tooltip will
* contain the error message. This approach is less intrusive than a
......@@ -47,9 +48,10 @@ struct BaseValidatingLineEditPrivate;
*
* The widget has a concept of an "initialText" which can be something like
* "<Enter name here>". This results in state 'DisplayingInitialText', which
* is not valid, but is not marked red. */
class QWORKBENCH_UTILS_EXPORT BaseValidatingLineEdit : public QLineEdit {
* is not valid, but is not marked red.
*/
class QWORKBENCH_UTILS_EXPORT BaseValidatingLineEdit : public QLineEdit
{
Q_OBJECT
Q_DISABLE_COPY(BaseValidatingLineEdit)
Q_PROPERTY(QString initialText READ initialText WRITE setInitialText DESIGNABLE true)
......@@ -97,4 +99,5 @@ private:
} // namespace Utils
} // namespace Core
#endif // BASEVALIDATINGLINEEDIT_H
......@@ -84,8 +84,11 @@ bool ClassNameValidatingLineEdit::validate(const QString &value, QString *errorM
if (errorMessage)
*errorMessage = tr("The class name must not contain namespace delimiters.");
return false;
}
if (!m_d->m_nameRegexp.exactMatch(value)) {
} else if (value.isEmpty()) {
if (errorMessage)
*errorMessage = tr("Please enter a class name.");
return false;
} else if (!m_d->m_nameRegexp.exactMatch(value)) {
if (errorMessage)
*errorMessage = tr("The class name contains invalid characters.");
return false;
......
......@@ -35,6 +35,10 @@
namespace Core {
namespace Utils {
/**
* A control that let's the user choose a file name, based on a QLineEdit. Has
* some validation logic for embedding into QWizardPage.
*/
class QWORKBENCH_UTILS_EXPORT FileNameValidatingLineEdit : public BaseValidatingLineEdit
{
Q_OBJECT
......@@ -47,6 +51,10 @@ public:
bool allowDirectories = false,
QString *errorMessage = 0);
/**
* Sets whether entering directories is allowed. This will enable the user
* to enter slashes in the filename. Default is off.
*/
bool allowDirectories() const;
void setAllowDirectories(bool v);
......
......@@ -30,10 +30,6 @@
#include "filewizardpage.h"
#include "ui_filewizardpage.h"
#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtGui/QMessageBox>
namespace Core {
namespace Utils {
......@@ -103,6 +99,16 @@ bool FileWizardPage::isComplete() const
return m_d->m_complete;
}
void FileWizardPage::setNameLabel(const QString &label)
{
m_d->m_ui.nameLabel->setText(label);
}
void FileWizardPage::setPathLabel(const QString &label)
{
m_d->m_ui.pathLabel->setText(label);
}
void FileWizardPage::slotValidChanged()
{
const bool newComplete = m_d->m_ui.pathChooser->isValid() && m_d->m_ui.nameLineEdit->isValid();
......
......@@ -39,10 +39,15 @@ namespace Utils {
struct FileWizardPagePrivate;
/* Standard wizard page for a single file letting the user choose name
* and path. Sets the "FileNames" QWizard field. */
class QWORKBENCH_UTILS_EXPORT FileWizardPage : public QWizardPage {
/**
* Standard wizard page for a single file letting the user choose name
* and path. Sets the "FileNames" QWizard field.
*
* The name and path labels can be changed. By default they are simply "Name:"
* and "Path:".
*/
class QWORKBENCH_UTILS_EXPORT FileWizardPage : public QWizardPage
{
Q_OBJECT
Q_DISABLE_COPY(FileWizardPage)
Q_PROPERTY(QString path READ path WRITE setPath DESIGNABLE true)
......@@ -56,7 +61,10 @@ public:
virtual bool isComplete() const;
// Validate a base name entry field (potentially containing extension)
void setNameLabel(const QString &label);
void setPathLabel(const QString &label);
// Validate a base name entry field (potentially containing extension)
static bool validateBaseName(const QString &name, QString *errorMessage = 0);
signals:
......
......@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
<width>196</width>
<height>68</height>
</rect>
</property>
<property name="windowTitle">
......@@ -16,52 +16,26 @@
<property name="title">
<string>Choose the location</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QWidget" name="widget" native="true">
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<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="Core::Utils::FileNameValidatingLineEdit" name="nameLineEdit"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="pathLabel">
<property name="text">
<string>Path:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="Core::Utils::PathChooser" name="pathChooser" native="true"/>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="nameLabel">
<property name="text">
<string>Name:</string>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>201</height>
</size>
</widget>
</item>
<item row="0" column="1">
<widget class="Core::Utils::FileNameValidatingLineEdit" name="nameLineEdit"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="pathLabel">
<property name="text">
<string>Path:</string>
</property>
</spacer>
</widget>
</item>
<item row="1" column="1">
<widget class="Core::Utils::PathChooser" name="pathChooser" native="true"/>
</item>
</layout>
</widget>
......
......@@ -43,11 +43,12 @@ namespace Utils {
struct NewClassWidgetPrivate;
/* NewClassWidget: Utility widget for 'New Class' wizards. Prompts the user
/**
* NewClassWidget: Utility widget for 'New Class' wizards. Prompts the user
* to enter a class name (optionally derived from some base class) and file
* names for header, source and form files. Has some smart logic to derive
* the file names from the class name. */
* the file names from the class name.
*/
class QWORKBENCH_UTILS_EXPORT NewClassWidget : public QWidget
{
Q_DISABLE_COPY(NewClassWidget)
......@@ -115,8 +116,10 @@ public slots:
void setFormInputCheckable(bool v);
void setFormInputChecked(bool v);
/* The name passed into the new class widget will be reformatted to be a
* valid class name. */
/**
* The name passed into the new class widget will be reformatted to be a
* valid class name.
*/
void setClassName(const QString &suggestedName);
void setBaseClassName(const QString &);
void setPath(const QString &path);
......@@ -127,13 +130,15 @@ public slots:
void setAllowDirectories(bool v);
void setLowerCaseFiles(bool v);
/* Suggest a class name from the base class by stripping the leading 'Q'
/**
* Suggest a class name from the base class by stripping the leading 'Q'
* character. This will happen automagically if the base class combo
* changes until the class line edited is manually edited. */
* changes until the class line edited is manually edited.
*/
void suggestClassNameFromBase();
public slots:
// Trigger an update (after changing settings)
/** Trigger an update (after changing settings) */
void triggerUpdateFileNames();
private slots:
......
......@@ -39,10 +39,10 @@ namespace Utils {
struct PathChooserPrivate;
/* A Control that let's the user choose a path, consisting of a QLineEdit and
* a "Browse" button. Has some validation logic for embedding into
* QWizardPage. */
/**
* A control that let's the user choose a path, consisting of a QLineEdit and
* a "Browse" button. Has some validation logic for embedding into QWizardPage.
*/
class QWORKBENCH_UTILS_EXPORT PathChooser : public QWidget
{
Q_DISABLE_COPY(PathChooser)
......@@ -74,12 +74,12 @@ public:
QString path() const;
// Returns the suggested label title when used in a form layout
/** Returns the suggested label title when used in a form layout. */
static QString label();
virtual bool validatePath(const QString &path, QString *errorMessage = 0);
// Return the home directory, which needs some fixing under Windows.
/** Return the home directory, which needs some fixing under Windows. */
static QString homePath();
private:
......
......@@ -34,6 +34,7 @@
#define _WIN32_WINNT 0x0501 /* WinXP, needed for DebugActiveProcessStop() */
#include <windows.h>
#include <shellapi.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
......
......@@ -33,8 +33,15 @@
#include <QtCore/QDebug>
#include <QtCore/QPointer>
#include <QtCore/QTimer>
#include <QtCore/QSignalMapper>
#include <QtGui/QPushButton>
#include <QtGui/QMenu>
#include <QtGui/QLineEdit>
#include <QtGui/QFormLayout>
#include <QtGui/QHBoxLayout>
#include <QtGui/QToolButton>
#include <QtGui/QSpacerItem>
enum { debug = 0 };
......@@ -104,8 +111,12 @@ QList<int> selectedRows(const QAbstractItemView *view)
}
// ----------- SubmitEditorWidgetPrivate
struct SubmitEditorWidgetPrivate
{
// A pair of position/action to extend context menus
typedef QPair<int, QPointer<QAction> > AdditionalContextMenuAction;
SubmitEditorWidgetPrivate();
Ui::SubmitEditorWidget m_ui;
......@@ -113,13 +124,22 @@ struct SubmitEditorWidgetPrivate
bool m_filesChecked;
int m_fileNameColumn;
int m_activatedRow;
QList<AdditionalContextMenuAction> descriptionEditContextMenuActions;
QFormLayout *m_fieldLayout;
// Field entries (label, line edits)
typedef QPair<QString, QLineEdit*> FieldEntry;
QList<FieldEntry> m_fieldEntries;
QSignalMapper *m_fieldSignalMapper;
};
SubmitEditorWidgetPrivate::SubmitEditorWidgetPrivate() :
m_filesSelected(false),
m_filesChecked(false),
m_fileNameColumn(1),
m_activatedRow(-1)
m_activatedRow(-1),
m_fieldLayout(0),
m_fieldSignalMapper(0)
{
}
......@@ -128,6 +148,10 @@ SubmitEditorWidget::SubmitEditorWidget(QWidget *parent) :
m_d(new SubmitEditorWidgetPrivate)
{
m_d->m_ui.setupUi(this);
m_d->m_ui.description->setContextMenuPolicy(Qt::CustomContextMenu);
connect(m_d->m_ui.description, SIGNAL(customContextMenuRequested(QPoint)),
this, SLOT(editorCustomContextMenuRequested(QPoint)));
// File List
m_d->m_ui.fileView->setSelectionMode(QAbstractItemView::ExtendedSelection);
m_d->m_ui.fileView->setRootIsDecorated(false);
......@@ -212,7 +236,18 @@ QString SubmitEditorWidget::trimmedDescriptionText() const
QString SubmitEditorWidget::descriptionText() const
{
return m_d->m_ui.description->toPlainText();
QString rc = m_d->m_ui.description->toPlainText();
// append field entries
foreach(const SubmitEditorWidgetPrivate::FieldEntry &fe, m_d->m_fieldEntries) {
const QString fieldText = fe.second->text().trimmed();
if (!fieldText.isEmpty()) {
rc += fe.first;
rc += QLatin1Char(' ');
rc += fieldText;
rc += QLatin1Char('\n');
}
}
return rc;
}
void SubmitEditorWidget::setDescriptionText(const QString &text)
......@@ -381,6 +416,74 @@ void SubmitEditorWidget::insertTopWidget(QWidget *w)
m_d->m_ui.vboxLayout->insertWidget(0, w);
}
void SubmitEditorWidget::addDescriptionEditContextMenuAction(QAction *a)
{
m_d->descriptionEditContextMenuActions.push_back(SubmitEditorWidgetPrivate::AdditionalContextMenuAction(-1, a));
}
void SubmitEditorWidget::insertDescriptionEditContextMenuAction(int pos, QAction *a)
{
m_d->descriptionEditContextMenuActions.push_back(SubmitEditorWidgetPrivate::AdditionalContextMenuAction(pos, a));
}
void SubmitEditorWidget::editorCustomContextMenuRequested(const QPoint &pos)
{
QMenu *menu = m_d->m_ui.description->createStandardContextMenu();
// Extend
foreach (const SubmitEditorWidgetPrivate::AdditionalContextMenuAction &a, m_d->descriptionEditContextMenuActions) {
if (a.second) {
if (a.first >= 0) {
menu->insertAction(menu->actions().at(a.first), a.second);
} else {
menu->addAction(a.second);
}
}
}
menu->exec(m_d->m_ui.description->mapToGlobal(pos));
delete menu;
}
QLineEdit *SubmitEditorWidget::addField(const QString &label, bool hasDialogButton)
{
// Insert the form layout below the editor
if (!m_d->m_fieldLayout) {
QHBoxLayout *outerLayout = new QHBoxLayout;
m_d->m_fieldLayout = new QFormLayout;
outerLayout->addLayout(m_d->m_fieldLayout);
outerLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Ignored));
QBoxLayout *descrLayout = qobject_cast<QBoxLayout*>(m_d->m_ui.descriptionBox->layout());
Q_ASSERT(descrLayout);
descrLayout->addLayout(outerLayout);
}
if (hasDialogButton && !m_d->m_fieldSignalMapper) {
m_d->m_fieldSignalMapper = new QSignalMapper;
connect(m_d->m_fieldSignalMapper, SIGNAL(mapped(int)), this, SIGNAL(fieldDialogRequested(int)));
}
// Add a field row consisting of label and line edit
QLineEdit *lineEdit = new QLineEdit;
QHBoxLayout *fieldLayout = new QHBoxLayout;
fieldLayout->addWidget(lineEdit);
if (hasDialogButton) {
QToolButton *dialogButton = new QToolButton;
dialogButton->setText(tr("..."));
connect(dialogButton, SIGNAL(clicked()), m_d->m_fieldSignalMapper, SLOT(map()));
m_d->m_fieldSignalMapper->setMapping(dialogButton, m_d->m_fieldEntries.size());
fieldLayout->addWidget(dialogButton);
}
QToolButton *clearButton = new QToolButton;
clearButton->setText(tr("Clear"));
connect(clearButton, SIGNAL(clicked()), lineEdit, SLOT(clear()));
fieldLayout->addWidget(clearButton);
m_d->m_fieldLayout->addRow(label, fieldLayout);
m_d->m_fieldEntries.push_back(SubmitEditorWidgetPrivate::FieldEntry(label, lineEdit));
return lineEdit;
}
QLineEdit *SubmitEditorWidget::fieldLineEdit(int i) const
{
return m_d->m_fieldEntries.at(i).second;
}
} // namespace Utils
} // namespace Core
......
......@@ -41,6 +41,7 @@ class QListWidgetItem;
class QAction;
class QAbstractItemModel;
class QModelIndex;
class QLineEdit;
QT_END_NAMESPACE
namespace Core {
......@@ -104,10 +105,20 @@ public:
QPlainTextEdit *descriptionEdit() const;
void addDescriptionEditContextMenuAction(QAction *a);
void insertDescriptionEditContextMenuAction(int pos, QAction *a);
// Fields are additional fields consisting of a Label and a Line Edit.
// A field dialog is wired to a button labeled "..." that pops up a chooser
// resulting in text being set
QLineEdit *addField(const QString &label, bool hasDialogButton);
QLineEdit *fieldLineEdit(int i) const;
signals:
void diffSelected(const QStringList &);
void fileSelectionChanged(bool someFileSelected);
void fileCheckStateChanged(bool someFileChecked);
void fieldDialogRequested(int);
protected:
virtual void changeEvent(QEvent *e);
......@@ -120,6 +131,7 @@ private slots:
void updateActions();
void updateSubmitAction();
void updateDiffAction();
void editorCustomContextMenuRequested(const QPoint &);
private:
bool hasSelection() const;
......
......@@ -501,7 +501,7 @@ void BookmarkManager::documentPrevNext(bool next)
}
Core::EditorManager *em = Core::EditorManager::instance();
em->addCurrentPositionToNavigationHistory(true);
em->addCurrentPositionToNavigationHistory();
if (next) {
if (nextLine == -1)
editor->gotoLine(firstLine);
......@@ -513,7 +513,6 @@ void BookmarkManager::documentPrevNext(bool next)
else
editor->gotoLine(prevLine);
}
em->addCurrentPositionToNavigationHistory();
}
void BookmarkManager::next()
......
......@@ -202,7 +202,6 @@ void MakeStep::removeDirectory(const QString &dir)
m_openDirectories.remove(dir);
}
CMakeProject *MakeStep::project() const
{
return m_pro;
......
......@@ -30,18 +30,37 @@
#include "settingsdialog.h"
#include <extensionsystem/pluginmanager.h>
#include "icore.h"
#include <QtCore/QSettings>
#include <QtGui/QHeaderView>
#include <QtGui/QPushButton>
namespace {
struct PageData {
int index;
QString category;
QString id;
};
}
Q_DECLARE_METATYPE(::PageData);
using namespace Core;
using namespace Core::Internal;
SettingsDialog::SettingsDialog(QWidget *parent, const QString &initialCategory,
const QString &initialPage)
SettingsDialog::SettingsDialog(QWidget *parent, const QString &categoryId,
const QString &pageId)
: QDialog(parent), m_applied(false)
{
setupUi(this);
QString initialCategory = categoryId;
QString initialPage = pageId;
if (initialCategory.isEmpty() && initialPage.isEmpty()) {
QSettings *settings = ICore::instance()->settings();
initialCategory = settings->value("General/LastPreferenceCategory", QVariant(QString())).toString();
initialPage = settings->value("General/LastPreferencePage", QVariant(QString())).toString();
}
buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
connect(buttonBox->button(QDialogButtonBox::Apply), SIGNAL(clicked()), this, SLOT(apply()));
......@@ -50,7 +69,7 @@ SettingsDialog::SettingsDialog(QWidget *parent, const QString &initialCategory,
pageTree->header()->setVisible(false);
connect(pageTree, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
this, SLOT(pageSelected(QTreeWidgetItem *)));
this, SLOT(pageSelected()));
QMap<QString, QTreeWidgetItem *> categories;
......@@ -59,9 +78,14 @@ SettingsDialog::SettingsDialog(QWidget *parent, const QString &initialCategory,
int index = 0;
foreach (IOptionsPage *page, pages) {
PageData pageData;
pageData.index = index;
pageData.category = page->category();
pageData.id = page->id();
QTreeWidgetItem *item = new QTreeWidgetItem;
item->setText(0, page->trName());
item->setData(0, Qt::UserRole, index);
item->setData(0, Qt::UserRole, qVariantFromValue(pageData));
QStringList categoriesId = page->category().split(QLatin1Char('|'));
QStringList trCategories = page->trCategory().split(QLatin1Char('|'));
......@@ -71,7 +95,7 @@ SettingsDialog::SettingsDialog(QWidget *parent, const QString &initialCategory,
if (!categories.contains(currentCategory)) {
treeitem = new QTreeWidgetItem(pageTree);
treeitem->setText(0, trCategories.at(0));
treeitem->setData(0, Qt::UserRole, index);
treeitem->setData(0, Qt::UserRole, qVariantFromValue(pageData));
categories.insert(currentCategory, treeitem);
}
......@@ -81,7 +105,7 @@ SettingsDialog::SettingsDialog(QWidget *parent, const QString &initialCategory,
treeitem = new QTreeWidgetItem(categories.value(currentCategory));
currentCategory += QLatin1Char('|') + categoriesId.at(catCount);
treeitem->setText(0, trCategories.at(catCount));
treeitem->setData(0, Qt::UserRole, index);
treeitem->setData(0, Qt::UserRole, qVariantFromValue(pageData));