/*********************************************************************** * * Copyright (C) 2014-2018 wereturtle * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * ***********************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ThemeSelectionDialog.h" #include "ThemeFactory.h" #include "ThemePreviewer.h" #include "ThemeEditorDialog.h" #include "MessageBoxHelper.h" #define GW_LIST_WIDGET_ICON_WIDTH 200 #define GW_LIST_WIDGET_ICON_HEIGHT 125 ThemeSelectionDialog::ThemeSelectionDialog ( const QString& currentThemeName, QWidget* parent ) : QDialog(parent) { qreal dpr = 1.0; #if QT_VERSION >= 0x050600 dpr = devicePixelRatioF(); #endif iconWidth = GW_LIST_WIDGET_ICON_WIDTH * dpr; iconHeight = GW_LIST_WIDGET_ICON_HEIGHT * dpr; this->setWindowTitle(tr("Themes")); this->setAttribute(Qt::WA_DeleteOnClose); QGridLayout* layout = new QGridLayout(); QStringList availableThemes = ThemeFactory::getInstance()->getAvailableThemes(); // Find view sizes int focush = style()->pixelMetric(QStyle::PM_FocusFrameHMargin); int focusv = style()->pixelMetric(QStyle::PM_FocusFrameVMargin); int frame = style()->pixelMetric(QStyle::PM_DefaultFrameWidth); int scrollbar = style()->pixelMetric(QStyle::PM_SliderThickness) + style()->pixelMetric(QStyle::PM_ScrollBarExtent); const int spacing = 10; const int rowCount = 3; const int columnCount = 4; QSize viewSize ( ((GW_LIST_WIDGET_ICON_WIDTH + frame + focush + (spacing * 2)) * columnCount) + scrollbar, (GW_LIST_WIDGET_ICON_HEIGHT + fontMetrics().height() + frame + focusv + (spacing * 2)) * rowCount ); // Set up theme list themeListWidget = new QListWidget(this); themeListWidget->setSortingEnabled(true); themeListWidget->setFlow(QListView::LeftToRight); themeListWidget->setViewMode(QListView::IconMode); themeListWidget->setIconSize(QSize(GW_LIST_WIDGET_ICON_WIDTH, GW_LIST_WIDGET_ICON_HEIGHT)); themeListWidget->setSpacing(spacing); themeListWidget->setMovement(QListView::Static); themeListWidget->setResizeMode(QListView::Adjust); themeListWidget->setSelectionMode(QAbstractItemView::SingleSelection); themeListWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); themeListWidget->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); themeListWidget->setWordWrap(true); themeListWidget->setUniformItemSizes(true); themeListWidget->setMinimumSize(viewSize); for (int i = 0; i < availableThemes.size(); i++) { QString themeName = availableThemes[i]; QString err; QIcon themeIcon; Theme theme = ThemeFactory::getInstance()->loadTheme(themeName, err); if (!err.isNull()) { themeIcon = QIcon(":resources/images/unavailable.svg"); } else { ThemePreviewer previewer(theme, iconWidth, iconHeight); themeIcon = previewer.getIcon(); } QListWidgetItem* item = new QListWidgetItem ( themeIcon, themeName, themeListWidget ); themeListWidget->insertItem(themeListWidget->count(), item); if (themeName == currentThemeName) { themeListWidget->setCurrentItem(item); currentTheme = theme; } } QDialogButtonBox* buttonBox = new QDialogButtonBox(Qt::Horizontal, this); QPushButton* newThemeButton = new QPushButton(" + "); QPushButton* deleteThemeButton = new QPushButton(" - "); QPushButton* editThemeButton = new QPushButton(tr("Edit...")); buttonBox->addButton(newThemeButton, QDialogButtonBox::ActionRole); buttonBox->addButton(deleteThemeButton, QDialogButtonBox::ActionRole); buttonBox->addButton(editThemeButton, QDialogButtonBox::ActionRole); buttonBox->addButton(QDialogButtonBox::Close); layout->addWidget(themeListWidget, 0, 0, 1, 1); layout->addWidget(buttonBox, 1, 0, 1, 1); this->setLayout(layout); connect(buttonBox->button(QDialogButtonBox::Close), SIGNAL(clicked()), this, SLOT(close())); connect(newThemeButton, SIGNAL(clicked()), this, SLOT(onNewTheme())); connect(deleteThemeButton, SIGNAL(clicked()), this, SLOT(onDeleteTheme())); connect(editThemeButton, SIGNAL(clicked()), this, SLOT(onEditTheme())); connect(themeListWidget, SIGNAL(itemSelectionChanged()), this, SLOT(onThemeSelected())); currentThemeIsValid = true; currentThemeIsNew = false; } ThemeSelectionDialog::~ThemeSelectionDialog() { ; } void ThemeSelectionDialog::onThemeSelected() { QList selectedThemes = themeListWidget->selectedItems(); QString themeName; Theme theme; if ( selectedThemes.isEmpty() || selectedThemes[0]->text().isNull() || selectedThemes[0]->text().isEmpty() ) { return; } currentThemeIsValid = true; themeName = selectedThemes[0]->text(); QString err; if (!currentThemeIsNew) { theme = ThemeFactory::getInstance()->loadTheme(themeName, err); currentTheme = theme; if (!err.isNull()) { // Show an error dialog telling the user that the theme could not // be loaded. // MessageBoxHelper::critical ( this, tr("Unable to load theme."), err ); currentTheme.setName(themeName); currentThemeIsValid = false; return; } } else { theme = currentTheme; } emit applyTheme(theme); } void ThemeSelectionDialog::onNewTheme() { QString err = QString(); Theme newTheme; QList selectedThemes = themeListWidget->selectedItems(); if (selectedThemes.size() > 0) { newTheme = ThemeFactory::getInstance()->loadTheme ( selectedThemes[0]->text(), err ); } else { newTheme = ThemeFactory::getInstance()->getDefaultTheme(); } newTheme.setBuiltIn(false); // It doesn't matter if there was an error, since loadTheme will // return a default, built-in theme if it fails. // err = QString(); QIcon themeIcon; if (!err.isNull()) { themeIcon = QIcon(":resources/images/unavailable.svg"); } else { ThemePreviewer previewer(newTheme, iconWidth, iconHeight); themeIcon = previewer.getIcon(); } newTheme.setName(ThemeFactory::getInstance()->generateUntitledThemeName()); ThemeFactory::getInstance()->saveTheme(newTheme.getName(), newTheme, err); QListWidgetItem* item = new QListWidgetItem(themeIcon, newTheme.getName(), themeListWidget); themeListWidget->insertItem(themeListWidget->count(), item); currentThemeIsNew = true; currentTheme = newTheme; currentThemeIsValid = true; this->themeListWidget->setCurrentItem(item); ThemeEditorDialog themeEditorDialog(newTheme, this); connect(&themeEditorDialog, SIGNAL(themeUpdated(Theme)), this, SLOT(onThemeUpdated(Theme))); themeEditorDialog.exec(); } void ThemeSelectionDialog::onDeleteTheme() { QList selectedThemes = themeListWidget->selectedItems(); if (selectedThemes.isEmpty()) { // Ignore if no theme is selected. return; } // If the theme is one of the built in themes, display an error. // if (currentTheme.isBuiltIn()) { MessageBoxHelper::critical ( this, tr("Cannot delete theme."), tr("Sorry, this is a built-in theme that cannot be deleted.") ); return; } QString themeName = selectedThemes[0]->text(); int result = MessageBoxHelper::question ( this, tr("Are you sure you want to permanently delete the '%1' theme?") .arg(themeName), QString(), QMessageBox::Yes | QMessageBox::No, QMessageBox::No ); if (QMessageBox::Yes == result) { QString err; ThemeFactory::getInstance()->deleteTheme(themeName, err); if (!err.isNull()) { MessageBoxHelper::critical ( this, tr("Failed to delete theme."), err ); } else { int row = themeListWidget->row(selectedThemes[0]); QListWidgetItem* item = themeListWidget->takeItem(row); if (NULL != item) { delete item; item = NULL; } } } } void ThemeSelectionDialog::onEditTheme() { QList selectedThemes = themeListWidget->selectedItems(); if (!selectedThemes.isEmpty()) { // If the theme is one of the built in themes, display an error. // if (currentTheme.isBuiltIn()) { MessageBoxHelper::critical ( this, tr("Cannot edit theme."), tr("Sorry, this is a built-in theme that cannot be edited.") ); return; } Theme themeToEdit = currentTheme; if (!currentThemeIsValid) { QString err; themeToEdit = ThemeFactory::getInstance()->loadTheme("", err); themeToEdit.setName(currentTheme.getName()); } ThemeEditorDialog themeEditorDialog(themeToEdit, this); connect(&themeEditorDialog, SIGNAL(themeUpdated(Theme)), this, SLOT(onThemeUpdated(Theme))); themeEditorDialog.exec(); } } void ThemeSelectionDialog::onThemeUpdated(const Theme& theme) { // Update theme name and preview icon, as applicable. // QList selectedThemes = themeListWidget->selectedItems(); if (!selectedThemes.isEmpty()) { QListWidgetItem* item = selectedThemes[0]; if (NULL != item) { if (theme.getName() != currentTheme.getName()) { item->setText(theme.getName()); } currentTheme = theme; currentThemeIsValid = true; ThemePreviewer previewer(theme, iconWidth, iconHeight); QIcon themeIcon = previewer.getIcon(); item->setIcon(themeIcon); } } currentThemeIsNew = false; // Notify of theme change so it can be applied. emit applyTheme(theme); }