Files
qt-creator/src/plugins/coreplugin/themechooser.cpp
Eike Ziller 05bf915c03 Core: Refactor argument handling
Split up getting the data from the arguments list and actually applying
the values, and move the details of theme creation and application to
better places.

This gets rid of ugly control flow details like that
CorePlugin::initialize created the action manager before calling
parseArguments, because that is needed to apply the presentation mode
argument setting, and parseArguments created the main window because
that needs to be created _after_ setting the theme (which can be
overridden by command line argument), but _before_ applying the override
color argument setting.

Change-Id: I9c99305b6efbfcc4b37cea9e5c70d816a621963b
Reviewed-by: David Schulz <david.schulz@qt.io>
2016-11-02 11:10:18 +00:00

239 lines
7.1 KiB
C++

/****************************************************************************
**
** Copyright (C) 2016 Thorben Kroeger <thorbenkroeger@gmail.com>.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** 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
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "coreconstants.h"
#include "icore.h"
#include "manhattanstyle.h"
#include "themechooser.h"
#include <utils/algorithm.h>
#include <utils/theme/theme.h>
#include <utils/theme/theme_p.h>
#include <QAbstractListModel>
#include <QComboBox>
#include <QCoreApplication>
#include <QDebug>
#include <QDir>
#include <QHBoxLayout>
#include <QMessageBox>
#include <QSettings>
#include <QSpacerItem>
using namespace Utils;
static const char themeNameKey[] = "ThemeName";
namespace Core {
namespace Internal {
ThemeEntry::ThemeEntry(Id id, const QString &filePath)
: m_id(id)
, m_filePath(filePath)
{
}
Id ThemeEntry::id() const
{
return m_id;
}
QString ThemeEntry::displayName() const
{
if (m_displayName.isEmpty() && !m_filePath.isEmpty()) {
QSettings settings(m_filePath, QSettings::IniFormat);
m_displayName = settings.value(QLatin1String(themeNameKey),
QCoreApplication::tr("unnamed")).toString();
}
return m_displayName;
}
QString ThemeEntry::filePath() const
{
return m_filePath;
}
class ThemeListModel : public QAbstractListModel
{
public:
ThemeListModel(QObject *parent = 0):
QAbstractListModel(parent)
{
}
int rowCount(const QModelIndex &parent) const override
{
return parent.isValid() ? 0 : m_themes.size();
}
QVariant data(const QModelIndex &index, int role) const override
{
if (role == Qt::DisplayRole)
return m_themes.at(index.row()).displayName();
return QVariant();
}
void removeTheme(int index)
{
beginRemoveRows(QModelIndex(), index, index);
m_themes.removeAt(index);
endRemoveRows();
}
void setThemes(const QList<ThemeEntry> &themes)
{
beginResetModel();
m_themes = themes;
endResetModel();
}
const ThemeEntry &themeAt(int index) const
{
return m_themes.at(index);
}
private:
QList<ThemeEntry> m_themes;
};
class ThemeChooserPrivate
{
public:
ThemeChooserPrivate(QWidget *widget);
~ThemeChooserPrivate();
public:
ThemeListModel *m_themeListModel;
QComboBox *m_themeComboBox;
};
ThemeChooserPrivate::ThemeChooserPrivate(QWidget *widget)
: m_themeListModel(new ThemeListModel)
, m_themeComboBox(new QComboBox)
{
QHBoxLayout *layout = new QHBoxLayout(widget);
layout->addWidget(m_themeComboBox);
layout->setMargin(0);
auto horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
layout->addSpacerItem(horizontalSpacer);
m_themeComboBox->setModel(m_themeListModel);
const QList<ThemeEntry> themes = ThemeEntry::availableThemes();
const Id activeTheme = Id::fromString(creatorTheme()->id());
const int selected = Utils::indexOf(themes, Utils::equal(&ThemeEntry::id, activeTheme));
m_themeListModel->setThemes(themes);
if (selected >= 0)
m_themeComboBox->setCurrentIndex(selected);
}
ThemeChooserPrivate::~ThemeChooserPrivate()
{
delete m_themeListModel;
}
ThemeChooser::ThemeChooser(QWidget *parent) :
QWidget(parent)
{
d = new ThemeChooserPrivate(this);
}
ThemeChooser::~ThemeChooser()
{
delete d;
}
void ThemeChooser::apply()
{
const int index = d->m_themeComboBox->currentIndex();
if (index == -1)
return;
const QString themeId = d->m_themeListModel->themeAt(index).id().toString();
QSettings *settings = ICore::settings();
const QString currentThemeId = ThemeEntry::themeSetting().toString();
if (currentThemeId != themeId) {
QMessageBox::information(ICore::mainWindow(), tr("Restart Required"),
tr("The theme change will take effect after a restart of Qt Creator."));
// save filename of selected theme in global config
settings->setValue(QLatin1String(Constants::SETTINGS_THEME), themeId);
}
}
static void addThemesFromPath(const QString &path, QList<ThemeEntry> *themes)
{
static const QLatin1String extension("*.creatortheme");
QDir themeDir(path);
themeDir.setNameFilters(QStringList() << extension);
themeDir.setFilter(QDir::Files);
const QStringList themeList = themeDir.entryList();
foreach (const QString &fileName, themeList) {
QString id = QFileInfo(fileName).completeBaseName();
themes->append(ThemeEntry(Id::fromString(id), themeDir.absoluteFilePath(fileName)));
}
}
QList<ThemeEntry> ThemeEntry::availableThemes()
{
QList<ThemeEntry> themes;
static const QString installThemeDir = ICore::resourcePath() + QLatin1String("/themes");
static const QString userThemeDir = ICore::userResourcePath() + QLatin1String("/themes");
addThemesFromPath(installThemeDir, &themes);
if (themes.isEmpty())
qWarning() << "Warning: No themes found in installation: "
<< QDir::toNativeSeparators(installThemeDir);
// move default theme to front
int defaultIndex = Utils::indexOf(themes, Utils::equal(&ThemeEntry::id, Id(Constants::DEFAULT_THEME)));
if (defaultIndex > 0) { // == exists and not at front
ThemeEntry defaultEntry = themes.takeAt(defaultIndex);
themes.prepend(defaultEntry);
}
addThemesFromPath(userThemeDir, &themes);
return themes;
}
Id ThemeEntry::themeSetting()
{
return Id::fromSetting(ICore::settings()->value(QLatin1String(Constants::SETTINGS_THEME),
QLatin1String(Constants::DEFAULT_THEME)));
}
Theme *ThemeEntry::createTheme(Id id)
{
if (!id.isValid())
return nullptr;
const ThemeEntry entry = Utils::findOrDefault(availableThemes(),
Utils::equal(&ThemeEntry::id, id));
if (!entry.id().isValid())
return nullptr;
QSettings themeSettings(entry.filePath(), QSettings::IniFormat);
Theme *theme = new Theme(entry.id().toString());
theme->readSettings(themeSettings);
return theme;
}
} // namespace Internal
} // namespace Core