Commit bf738969 authored by Friedemann Kleint's avatar Friedemann Kleint

SettingsDialog: Polish

Use QGridLayout to align header label and QStackedLayout for the pages
(in code, as it is not available in Designer).
Derive new class FilterLineEdit for filter widgets based on a modified
version of FancyLineEdit and use that in settings.
Rubber-stamped-by: default avatarcon <qtc-committer@nokia.com>
parent cf975fc3
......@@ -63,14 +63,14 @@ static QString labelStyleSheet(FancyLineEdit::Side side)
class FancyLineEditPrivate : public QObject {
public:
explicit FancyLineEditPrivate(QLineEdit *parent);
explicit FancyLineEditPrivate(FancyLineEdit *parent);
virtual bool eventFilter(QObject *obj, QEvent *event);
const QString m_leftLabelStyleSheet;
const QString m_rightLabelStyleSheet;
QLineEdit *m_lineEdit;
FancyLineEdit *m_lineEdit;
QPixmap m_pixmap;
QMenu *m_menu;
QLabel *m_menuLabel;
......@@ -82,7 +82,7 @@ public:
};
FancyLineEditPrivate::FancyLineEditPrivate(QLineEdit *parent) :
FancyLineEditPrivate::FancyLineEditPrivate(FancyLineEdit *parent) :
QObject(parent),
m_leftLabelStyleSheet(labelStyleSheet(FancyLineEdit::Left)),
m_rightLabelStyleSheet(labelStyleSheet(FancyLineEdit::Right)),
......@@ -98,17 +98,21 @@ FancyLineEditPrivate::FancyLineEditPrivate(QLineEdit *parent) :
bool FancyLineEditPrivate::eventFilter(QObject *obj, QEvent *event)
{
if (!m_menu || obj != m_menuLabel)
if (obj != m_menuLabel)
return QObject::eventFilter(obj, event);
switch (event->type()) {
case QEvent::MouseButtonPress: {
const QMouseEvent *me = static_cast<QMouseEvent *>(event);
m_menu->exec(me->globalPos());
if (m_menu) {
m_menu->exec(me->globalPos());
} else {
emit m_lineEdit->buttonClicked();
}
return true;
}
case QEvent::FocusIn:
if (m_menuTabFocusTrigger) {
if (m_menuTabFocusTrigger && m_menu) {
m_lineEdit->setFocus();
m_menu->exec(m_menuLabel->mapToGlobal(m_menuLabel->rect().center()));
return true;
......@@ -161,6 +165,9 @@ void FancyLineEdit::updateStyleSheet(Side side)
sheet += QLatin1Char(';');
if (m_d->m_showingHintText)
sheet += QLatin1String(" color: #BBBBBB;");
// Fix the stylesheet's clearing the size hint.
sheet += QLatin1String(" height: ");
sheet += QString::number(sizeHint().height());
sheet += QLatin1Char('}');
setStyleSheet(sheet);
}
......
......@@ -85,6 +85,9 @@ public:
// Convenience for accessing the text that returns "" in case of isShowingHintText().
QString typedText() const;
signals:
void buttonClicked();
public slots:
void setPixmap(const QPixmap &pixmap);
void setHintText(const QString &ht);
......@@ -97,6 +100,7 @@ protected:
virtual void focusOutEvent(QFocusEvent *e);
private:
friend class Utils::FancyLineEditPrivate;
bool isSideStored() const;
void updateMenuLabel();
void positionMenuLabel();
......
/**************************************************************************
**
** 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 "filterlineedit.h"
namespace Utils {
FilterLineEdit::FilterLineEdit(QWidget *parent) :
FancyLineEdit(parent),
m_lastFilterText(typedText())
{
setSide(Utils::FancyLineEdit::Right);
setPixmap(QPixmap(QLatin1String(":/utils/images/reset.png")));
setHintText(tr("Type to filter"));
connect(this, SIGNAL(buttonClicked()), this, SLOT(clear()));
connect(this, SIGNAL(textChanged(QString)), this, SLOT(slotTextChanged()));
}
void FilterLineEdit::slotTextChanged()
{
const QString newlyTypedText = typedText();
if (newlyTypedText != m_lastFilterText) {
m_lastFilterText = newlyTypedText;
emit filterChanged(m_lastFilterText);
}
}
} // namespace Utils
/**************************************************************************
**
** 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.
**
**************************************************************************/
#ifndef FILTERLINEEDIT_H
#define FILTERLINEEDIT_H
#include "fancylineedit.h"
namespace Utils {
/* A fancy line edit customized for filtering purposes with a clear button. */
class QTCREATOR_UTILS_EXPORT FilterLineEdit : public FancyLineEdit
{
Q_OBJECT
public:
explicit FilterLineEdit(QWidget *parent = 0);
signals:
void filterChanged(const QString &);
private slots:
void slotTextChanged();
private:
QString m_lastFilterText;
};
} // namespace Utils
#endif // FILTERLINEEDIT_H
......@@ -37,7 +37,8 @@ SOURCES += reloadpromptutils.cpp \
fancymainwindow.cpp \
detailsbutton.cpp \
detailswidget.cpp \
changeset.cpp
changeset.cpp \
filterlineedit.cpp
win32 {
SOURCES += abstractprocess_win.cpp \
consoleprocess_win.cpp \
......@@ -82,7 +83,8 @@ HEADERS += utils_global.h \
fancymainwindow.h \
detailsbutton.h \
detailswidget.h \
changeset.h
changeset.h \
filterlineedit.h
FORMS += filewizardpage.ui \
projectintropage.ui \
newclasswidget.ui \
......
<RCC>
<qresource prefix="/utils" >
<file>images/removesubmitfield.png</file>
<file>images/reset.png</file>
</qresource>
</RCC>
......@@ -158,7 +158,6 @@ HEADERS += mainwindow.h \
settingsdatabase.h \
eventfilteringmainwindow.h
FORMS += dialogs/newdialog.ui \
dialogs/settingsdialog.ui \
dialogs/shortcutsettings.ui \
dialogs/saveitemsdialog.ui \
dialogs/openwithdialog.ui \
......
......@@ -33,20 +33,29 @@
#include "icore.h"
#include <utils/qtcassert.h>
#include <utils/filterlineedit.h>
#include <QtCore/QSettings>
#include <QtGui/QHeaderView>
#include <QtGui/QPushButton>
#include <QtGui/QStandardItemModel>
#include <QtGui/QStandardItem>
#include <QtGui/QSortFilterProxyModel>
#include <QtGui/QItemSelectionModel>
#include <QtGui/QHBoxLayout>
#include <QtGui/QIcon>
#include <QtGui/QLabel>
#include <QtGui/QVBoxLayout>
#include <QtGui/QHBoxLayout>
#include <QtGui/QPushButton>
#include <QtGui/QToolButton>
#include <QtGui/QToolBar>
#include <QtGui/QSpacerItem>
#include <QtGui/QStyle>
#include <QtGui/QStackedLayout>
#include <QtGui/QGridLayout>
#include <QtGui/QLineEdit>
#include <QtGui/QFrame>
#include <QtGui/QDialogButtonBox>
#include <QtGui/QTreeView>
#include <QtGui/QApplication>
enum ItemType { CategoryItem, PageItem };
......@@ -186,9 +195,13 @@ SettingsDialog::SettingsDialog(QWidget *parent, const QString &categoryId,
m_pages(ExtensionSystem::PluginManager::instance()->getObjects<IOptionsPage>()),
m_proxyModel(new PageFilterModel),
m_model(0),
m_applied(false)
m_applied(false),
m_stackedLayout(new QStackedLayout),
m_filterLineEdit(new Utils::FilterLineEdit),
m_pageTree(new QTreeView),
m_headerLabel(new QLabel)
{
setupUi(this);
createGui();
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
#ifdef Q_OS_MAC
setWindowTitle(tr("Preferences"));
......@@ -202,73 +215,77 @@ SettingsDialog::SettingsDialog(QWidget *parent, const QString &categoryId,
initialCategory = settings->value(QLatin1String(categoryKeyC), QVariant(QString())).toString();
initialPage = settings->value(QLatin1String(pageKeyC), QVariant(QString())).toString();
}
buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
connect(buttonBox->button(QDialogButtonBox::Apply), SIGNAL(clicked()), this, SLOT(apply()));
// Create pages with title labels with a larger, bold font, left-aligned
// with the group boxes of the page.
const int pageCount = m_pages.size();
QFont titleLabelFont;
const int leftMargin = qApp->style()->pixelMetric(QStyle::PM_LayoutLeftMargin) +
qApp->style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
for (int i = 0; i < pageCount; i++) {
// Title bar
QHBoxLayout *titleLayout = new QHBoxLayout;
titleLayout->addSpacerItem(new QSpacerItem(leftMargin, 0, QSizePolicy::Fixed, QSizePolicy::Ignored));
QLabel *titleLabel = new QLabel(m_pages.at(i)->trName());
if (i == 0) { // Create a bold header font from the default label font.
titleLabelFont = titleLabel->font();
titleLabelFont.setBold(true);
// Paranoia: Should a font be set in pixels...
const int pointSize = titleLabelFont.pointSize();
if (pointSize > 0)
titleLabelFont.setPointSize(pointSize + 2);
}
titleLabel->setFont(titleLabelFont);
titleLayout->addWidget(titleLabel);
// Page
QWidget *pageContainer =new QWidget;
QVBoxLayout *pageLayout = new QVBoxLayout(pageContainer);
pageLayout->addLayout(titleLayout);
pageLayout->addSpacerItem(new QSpacerItem(0, 6, QSizePolicy::Ignored, QSizePolicy::Fixed));
pageLayout->addWidget(m_pages.at(i)->createPage(0));
stackedPages->addWidget(pageContainer);
}
// foreach(IOptionsPage *page, m_pages)
// stackedPages->addWidget();
splitter->setCollapsible(1, false);
pageTree->header()->setVisible(false);
foreach(IOptionsPage *page, m_pages)
m_stackedLayout->addWidget(page->createPage(0));
QModelIndex initialIndex;
m_model = pageModel(m_pages, 0, initialCategory, initialPage, &initialIndex);
m_proxyModel->setFilterKeyColumn(0);
m_proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
m_proxyModel->setSourceModel(m_model);
pageTree->setModel(m_proxyModel);
pageTree->setSelectionMode(QAbstractItemView::SingleSelection);
connect(pageTree->selectionModel(), SIGNAL(currentRowChanged(QModelIndex,QModelIndex)),
m_pageTree->setModel(m_proxyModel);
m_pageTree->setSelectionMode(QAbstractItemView::SingleSelection);
connect(m_pageTree->selectionModel(), SIGNAL(currentRowChanged(QModelIndex,QModelIndex)),
this, SLOT(currentChanged(QModelIndex,QModelIndex)));
if (initialIndex.isValid()) {
const QModelIndex proxyIndex = m_proxyModel->mapFromSource(initialIndex);
pageTree->selectionModel()->setCurrentIndex(proxyIndex, QItemSelectionModel::ClearAndSelect);
m_pageTree->selectionModel()->setCurrentIndex(proxyIndex, QItemSelectionModel::ClearAndSelect);
}
m_pageTree->resizeColumnToContents(0);
QList<int> sizes;
sizes << 150 << 300;
splitter->setSizes(sizes);
splitter->setStretchFactor(splitter->indexOf(pageTree), 0);
splitter->setStretchFactor(splitter->indexOf(layoutWidget), 1);
filterClearButton->setIcon(QIcon(QLatin1String(":/core/images/reset.png")));
connect(filterClearButton, SIGNAL(clicked()), filterLineEdit, SLOT(clear()));
// The order of the slot connection matters here, the filter slot
// opens the matching page after the model has filtered.
connect(filterLineEdit, SIGNAL(textChanged(QString)),
connect(m_filterLineEdit, SIGNAL(filterChanged(QString)),
m_proxyModel, SLOT(setFilterFixedString(QString)));
connect(filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(filter(QString)));
connect(m_filterLineEdit, SIGNAL(filterChanged(QString)), this, SLOT(filter(QString)));
}
void SettingsDialog::createGui()
{
// Header label with large font and a bit of spacing (align with group boxes)
QFont headerLabelFont = m_headerLabel->font();
headerLabelFont.setBold(true);
// Paranoia: Should a font be set in pixels...
const int pointSize = headerLabelFont.pointSize();
if (pointSize > 0)
headerLabelFont.setPointSize(pointSize + 2);
m_headerLabel->setFont(headerLabelFont);
QHBoxLayout *headerHLayout = new QHBoxLayout;
const int leftMargin = qApp->style()->pixelMetric(QStyle::PM_LayoutLeftMargin) +
qApp->style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
headerHLayout->addSpacerItem(new QSpacerItem(leftMargin, 0, QSizePolicy::Fixed, QSizePolicy::Ignored));
headerHLayout->addWidget(m_headerLabel);
// Tree
m_pageTree->header()->setVisible(false);
m_stackedLayout->setMargin(0);
// Separator Line
QFrame *bottomLine = new QFrame;
bottomLine->setFrameShape(QFrame::HLine);
bottomLine->setFrameShadow(QFrame::Sunken);
// Button box
QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Apply|QDialogButtonBox::Cancel);
buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
connect(buttonBox->button(QDialogButtonBox::Apply), SIGNAL(clicked()), this, SLOT(apply()));
connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
QGridLayout *mainGridLayout = new QGridLayout;
mainGridLayout->addWidget(m_filterLineEdit, 0, 0, 1, 1);
mainGridLayout->addLayout(headerHLayout, 0, 1, 1, 1);
mainGridLayout->addWidget(m_pageTree, 1, 0, 2, 1);
mainGridLayout->addLayout(m_stackedLayout, 1, 1, 1, 1);
mainGridLayout->addWidget(bottomLine, 2, 1, 1, 1);
mainGridLayout->addWidget(buttonBox, 3, 0, 1, 2);
mainGridLayout->setColumnStretch(0, 1);
mainGridLayout->setColumnStretch(1, 4);
setLayout(mainGridLayout);
}
SettingsDialog::~SettingsDialog()
......@@ -284,8 +301,9 @@ void SettingsDialog::showPage(const QStandardItem *item)
IOptionsPage *page = pageOfItem(item);
m_currentCategory = page->category();
m_currentPage = page->id();
stackedPages->setCurrentIndex(indexOfItem(item));
m_stackedLayout->setCurrentIndex(indexOfItem(item));
m_visitedPages.insert(page);
m_headerLabel->setText(page->trName());
}
break;
case CategoryItem:
......@@ -337,17 +355,17 @@ void SettingsDialog::filter(const QString &text)
{
// Filter cleared, collapse all.
if (text.isEmpty()) {
pageTree->collapseAll();
m_pageTree->collapseAll();
return;
}
// Expand match and select the first page. Note: This depends
// on the order of slot invocation, needs to be done after filtering
if (!m_proxyModel->rowCount(QModelIndex()))
return;
pageTree->expandAll();
m_pageTree->expandAll();
const QModelIndex firstVisiblePage = findPage(m_proxyModel);
if (firstVisiblePage.isValid())
pageTree->selectionModel()->setCurrentIndex(firstVisiblePage, QItemSelectionModel::ClearAndSelect);
m_pageTree->selectionModel()->setCurrentIndex(firstVisiblePage, QItemSelectionModel::ClearAndSelect);
}
void SettingsDialog::accept()
......@@ -376,6 +394,7 @@ void SettingsDialog::apply()
bool SettingsDialog::execDialog()
{
m_pageTree->setFocus();
m_applied = false;
exec();
return m_applied;
......
......@@ -30,10 +30,9 @@
#ifndef SETTINGSDIALOG_H
#define SETTINGSDIALOG_H
#include "ui_settingsdialog.h"
#include <QtCore/QList>
#include <QtCore/QSet>
#include <QtGui/QDialog>
#include "coreplugin/dialogs/ioptionspage.h"
......@@ -42,12 +41,21 @@ class QModelIndex;
class QStandardItemModel;
class QStandardItem;
class QSortFilterProxyModel;
class QStackedLayout;
class QAbstractButton;
class QLineEdit;
class QLabel;
class QTreeView;
QT_END_NAMESPACE
namespace Utils {
class FilterLineEdit;
}
namespace Core {
namespace Internal {
class SettingsDialog : public QDialog, public ::Ui::SettingsDialog
class SettingsDialog : public QDialog
{
Q_OBJECT
......@@ -72,6 +80,7 @@ private slots:
void filter(const QString &text);
private:
void createGui();
void showPage(const QStandardItem *item);
const QList<Core::IOptionsPage*> m_pages;
......@@ -82,6 +91,10 @@ private:
bool m_applied;
QString m_currentCategory;
QString m_currentPage;
QStackedLayout *m_stackedLayout;
Utils::FilterLineEdit *m_filterLineEdit;
QTreeView *m_pageTree;
QLabel *m_headerLabel;
};
} // namespace Internal
......
......@@ -50,7 +50,7 @@ const char * const CPPTOOLS_SETTINGSGROUP = "CppTools";
const char * const LOWERCASE_CPPFILES_KEY = "LowerCaseFiles";
enum { lowerCaseFilesDefault = 1 };
const char * const CPP_SETTINGS_ID = QT_TRANSLATE_NOOP("CppTools", "File Naming Conventions");
const char * const CPP_SETTINGS_ID = QT_TRANSLATE_NOOP("CppTools", "File Naming");
const char * const CPP_SETTINGS_CATEGORY = QT_TRANSLATE_NOOP("CppTools", "C++");
} // namespace Constants
......
......@@ -114,6 +114,18 @@ FancyLineEdit_CW::FancyLineEdit_CW(QObject *parent) :
{
}
FilterLineEdit_CW::FilterLineEdit_CW(QObject *parent) :
QObject(parent),
CustomWidget<Utils::FilterLineEdit>
(QLatin1String("<utils/filterlineedit.h>"),
false,
QLatin1String(groupC),
QIcon(),
QLatin1String("A Line edit customized for filtering"))
{
}
QtColorButton_CW::QtColorButton_CW(QObject *parent) :
QObject(parent),
CustomWidget<Utils::QtColorButton>
......@@ -293,6 +305,7 @@ WidgetCollection::WidgetCollection(QObject *parent) :
m_plugins.push_back(new LineColumnLabel_CW(this));
m_plugins.push_back(new PathChooser_CW(this));
m_plugins.push_back(new FancyLineEdit_CW(this));
m_plugins.push_back(new FilterLineEdit_CW(this));
m_plugins.push_back(new QtColorButton_CW(this));
m_plugins.push_back(new SubmitEditorWidget_CW(this));
m_plugins.push_back(new SubmitFieldWidget_CW(this));
......
......@@ -38,7 +38,7 @@
#include <utils/linecolumnlabel.h>
#include <utils/pathchooser.h>
#include <utils/projectnamevalidatinglineedit.h>
#include <utils/fancylineedit.h>
#include <utils/filterlineedit.h>
#include <utils/qtcolorbutton.h>
#include <utils/submiteditorwidget.h>
#include <utils/submitfieldwidget.h>
......@@ -131,6 +131,16 @@ public:
virtual QWidget *createWidget(QWidget *parent);
};
class FilterLineEdit_CW :
public QObject,
public CustomWidget<Utils::FilterLineEdit>
{
Q_OBJECT
Q_INTERFACES(QDesignerCustomWidgetInterface)
public:
explicit FilterLineEdit_CW(QObject *parent = 0);
};
class QtColorButton_CW :
public QObject,
public CustomWidget<Utils::QtColorButton>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment