ThemeDialog::ThemeDialog(Theme& theme, QWidget* parent) : QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint), m_theme(theme) { setWindowTitle(tr("Edit Theme")); setWindowModality(Qt::WindowModal); // Create name edit m_name = new QLineEdit(this); m_name->setText(m_theme.name()); connect(m_name, SIGNAL(textChanged(QString)), this, SLOT(checkNameAvailable())); QHBoxLayout* name_layout = new QHBoxLayout; name_layout->setMargin(0); name_layout->addWidget(new QLabel(tr("Name:"), this)); name_layout->addWidget(m_name); // Create scrollarea QWidget* contents = new QWidget(this); QScrollArea* scroll = new QScrollArea(this); scroll->setWidget(contents); scroll->setWidgetResizable(true); // Create text group QGroupBox* text_group = new QGroupBox(tr("Text"), contents); m_text_color = new ColorButton(text_group); m_text_color->setColor(m_theme.textColor()); connect(m_text_color, SIGNAL(changed(QColor)), this, SLOT(renderPreview())); m_font_names = new FontComboBox(text_group); m_font_names->setEditable(false); m_font_names->setCurrentFont(m_theme.textFont()); connect(m_font_names, SIGNAL(activated(int)), this, SLOT(fontChanged())); connect(m_font_names, SIGNAL(activated(int)), this, SLOT(renderPreview())); m_font_sizes = new QComboBox(text_group); m_font_sizes->setEditable(true); m_font_sizes->setMinimumContentsLength(3); connect(m_font_sizes, SIGNAL(editTextChanged(QString)), this, SLOT(renderPreview())); fontChanged(); m_misspelled_color = new ColorButton(text_group); m_misspelled_color->setColor(m_theme.misspelledColor()); connect(m_misspelled_color, SIGNAL(changed(QColor)), this, SLOT(renderPreview())); QHBoxLayout* font_layout = new QHBoxLayout; font_layout->addWidget(m_font_names); font_layout->addWidget(m_font_sizes); QFormLayout* text_layout = new QFormLayout(text_group); text_layout->setFieldGrowthPolicy(QFormLayout::FieldsStayAtSizeHint); text_layout->addRow(tr("Color:"), m_text_color); text_layout->addRow(tr("Font:"), font_layout); text_layout->addRow(tr("Misspelled:"), m_misspelled_color); // Create background group QGroupBox* background_group = new QGroupBox(tr("Window Background"), contents); m_background_color = new ColorButton(background_group); m_background_color->setColor(m_theme.backgroundColor()); connect(m_background_color, SIGNAL(changed(QColor)), this, SLOT(renderPreview())); m_background_image = new ImageButton(background_group); m_background_image->setImage(m_theme.backgroundImage(), m_theme.backgroundPath()); connect(m_background_image, SIGNAL(changed(QString)), this, SLOT(imageChanged())); m_clear_image = new QPushButton(tr("Remove"), background_group); connect(m_clear_image, SIGNAL(clicked()), m_background_image, SLOT(unsetImage())); m_background_type = new QComboBox(background_group); m_background_type->addItems(QStringList() << tr("No Image") << tr("Tiled") << tr("Centered") << tr("Stretched") << tr("Scaled") << tr("Zoomed")); m_background_type->setCurrentIndex(m_theme.backgroundType()); connect(m_background_type, SIGNAL(activated(int)), this, SLOT(renderPreview())); QVBoxLayout* image_layout = new QVBoxLayout; image_layout->setSpacing(0); image_layout->setMargin(0); image_layout->addWidget(m_background_image); image_layout->addWidget(m_clear_image); QFormLayout* background_layout = new QFormLayout(background_group); background_layout->setFieldGrowthPolicy(QFormLayout::FieldsStayAtSizeHint); background_layout->addRow(tr("Color:"), m_background_color); background_layout->addRow(tr("Image:"), image_layout); background_layout->addRow(tr("Type:"), m_background_type); // Create foreground group QGroupBox* foreground_group = new QGroupBox(tr("Text Background"), contents); m_foreground_color = new ColorButton(foreground_group); m_foreground_color->setColor(m_theme.foregroundColor()); connect(m_foreground_color, SIGNAL(changed(QColor)), this, SLOT(renderPreview())); m_foreground_opacity = new QSpinBox(foreground_group); m_foreground_opacity->setCorrectionMode(QSpinBox::CorrectToNearestValue); m_foreground_opacity->setSuffix(QLocale().percent()); m_foreground_opacity->setRange(theme.foregroundOpacity().minimumValue(), theme.foregroundOpacity().maximumValue()); m_foreground_opacity->setValue(m_theme.foregroundOpacity()); connect(m_foreground_opacity, SIGNAL(valueChanged(int)), this, SLOT(renderPreview())); m_foreground_position = new QComboBox(foreground_group); m_foreground_position->addItems(QStringList() << tr("Left") << tr("Centered") << tr("Right") << tr("Stretched")); m_foreground_position->setCurrentIndex(m_theme.foregroundPosition()); connect(m_foreground_position, SIGNAL(currentIndexChanged(int)), this, SLOT(positionChanged(int))); m_foreground_width = new QSpinBox(foreground_group); m_foreground_width->setCorrectionMode(QSpinBox::CorrectToNearestValue); m_foreground_width->setSuffix(tr(" pixels")); m_foreground_width->setRange(theme.foregroundWidth().minimumValue(), theme.foregroundWidth().maximumValue()); m_foreground_width->setValue(m_theme.foregroundWidth()); m_foreground_width->setEnabled(m_theme.foregroundPosition() != 3); connect(m_foreground_width, SIGNAL(valueChanged(int)), this, SLOT(renderPreview())); QFormLayout* foreground_layout = new QFormLayout(foreground_group); foreground_layout->setFieldGrowthPolicy(QFormLayout::FieldsStayAtSizeHint); foreground_layout->addRow(tr("Color:"), m_foreground_color); foreground_layout->addRow(tr("Opacity:"), m_foreground_opacity); foreground_layout->addRow(tr("Position:"), m_foreground_position); foreground_layout->addRow(tr("Width:"), m_foreground_width); // Create rounding group m_round_corners = new QGroupBox(tr("Round Text Background Corners"), contents); m_round_corners->setCheckable(true); m_round_corners->setChecked(m_theme.roundCornersEnabled()); connect(m_round_corners, SIGNAL(clicked()), this, SLOT(renderPreview())); m_corner_radius = new QSpinBox(m_round_corners); m_corner_radius->setCorrectionMode(QSpinBox::CorrectToNearestValue); m_corner_radius->setSuffix(tr(" pixels")); m_corner_radius->setRange(theme.cornerRadius().minimumValue(), theme.cornerRadius().maximumValue()); m_corner_radius->setValue(m_theme.cornerRadius()); connect(m_corner_radius, SIGNAL(valueChanged(int)), this, SLOT(renderPreview())); QFormLayout* corner_layout = new QFormLayout(m_round_corners); corner_layout->setFieldGrowthPolicy(QFormLayout::FieldsStayAtSizeHint); corner_layout->addRow(tr("Radius:"), m_corner_radius); // Create blur group m_blur = new QGroupBox(tr("Blur Text Background"), contents); m_blur->setCheckable(true); m_blur->setChecked(m_theme.blurEnabled()); connect(m_blur, SIGNAL(clicked()), this, SLOT(renderPreview())); m_blur_radius = new QSpinBox(m_blur); m_blur_radius->setCorrectionMode(QSpinBox::CorrectToNearestValue); m_blur_radius->setSuffix(tr(" pixels")); m_blur_radius->setRange(theme.blurRadius().minimumValue(), theme.blurRadius().maximumValue()); m_blur_radius->setValue(m_theme.blurRadius()); connect(m_blur_radius, SIGNAL(valueChanged(int)), this, SLOT(renderPreview())); QFormLayout* blur_layout = new QFormLayout(m_blur); blur_layout->setFieldGrowthPolicy(QFormLayout::FieldsStayAtSizeHint); blur_layout->addRow(tr("Radius:"), m_blur_radius); // Create shadow group m_shadow = new QGroupBox(tr("Text Background Drop Shadow"), contents); m_shadow->setCheckable(true); m_shadow->setChecked(m_theme.shadowEnabled()); connect(m_shadow, SIGNAL(clicked()), this, SLOT(renderPreview())); m_shadow_color = new ColorButton(m_shadow); m_shadow_color->setColor(m_theme.shadowColor()); connect(m_shadow_color, SIGNAL(changed(QColor)), this, SLOT(renderPreview())); m_shadow_radius = new QSpinBox(m_shadow); m_shadow_radius->setCorrectionMode(QSpinBox::CorrectToNearestValue); m_shadow_radius->setSuffix(tr(" pixels")); m_shadow_radius->setRange(theme.shadowRadius().minimumValue(), theme.shadowRadius().maximumValue()); m_shadow_radius->setValue(m_theme.shadowRadius()); connect(m_shadow_radius, SIGNAL(valueChanged(int)), this, SLOT(renderPreview())); m_shadow_offset = new QSpinBox(m_shadow); m_shadow_offset->setCorrectionMode(QSpinBox::CorrectToNearestValue); m_shadow_offset->setSuffix(tr(" pixels")); m_shadow_offset->setRange(theme.shadowOffset().minimumValue(), theme.shadowOffset().maximumValue()); m_shadow_offset->setValue(m_theme.shadowOffset()); connect(m_shadow_offset, SIGNAL(valueChanged(int)), this, SLOT(renderPreview())); QFormLayout* shadow_layout = new QFormLayout(m_shadow); shadow_layout->setFieldGrowthPolicy(QFormLayout::FieldsStayAtSizeHint); shadow_layout->addRow(tr("Color:"), m_shadow_color); shadow_layout->addRow(tr("Radius:"), m_shadow_radius); shadow_layout->addRow(tr("Vertical Offset:"), m_shadow_offset); // Create margins group QGroupBox* margins_group = new QGroupBox(tr("Margins"), contents); m_foreground_margin = new QSpinBox(margins_group); m_foreground_margin->setCorrectionMode(QSpinBox::CorrectToNearestValue); m_foreground_margin->setSuffix(tr(" pixels")); m_foreground_margin->setRange(theme.foregroundMargin().minimumValue(), theme.foregroundMargin().maximumValue()); m_foreground_margin->setValue(m_theme.foregroundMargin()); connect(m_foreground_margin, SIGNAL(valueChanged(int)), this, SLOT(renderPreview())); m_foreground_padding = new QSpinBox(margins_group); m_foreground_padding->setCorrectionMode(QSpinBox::CorrectToNearestValue); m_foreground_padding->setSuffix(tr(" pixels")); m_foreground_padding->setRange(theme.foregroundPadding().minimumValue(), theme.foregroundPadding().maximumValue()); m_foreground_padding->setValue(m_theme.foregroundPadding()); connect(m_foreground_padding, SIGNAL(valueChanged(int)), this, SLOT(renderPreview())); QFormLayout* margins_layout = new QFormLayout(margins_group); margins_layout->setFieldGrowthPolicy(QFormLayout::FieldsStayAtSizeHint); margins_layout->addRow(tr("Window:"), m_foreground_margin); margins_layout->addRow(tr("Page:"), m_foreground_padding); // Create line spacing group QGroupBox* line_spacing = new QGroupBox(tr("Line Spacing"), contents); m_line_spacing_type = new QComboBox(line_spacing); m_line_spacing_type->setEditable(false); m_line_spacing_type->addItems(QStringList() << tr("Single") << tr("1.5 Lines") << tr("Double") << tr("Proportional")); m_line_spacing_type->setCurrentIndex(3); m_line_spacing = new QSpinBox(line_spacing); m_line_spacing->setSuffix(QLocale().percent()); m_line_spacing->setRange(theme.lineSpacing().minimumValue(), theme.lineSpacing().maximumValue()); m_line_spacing->setValue(m_theme.lineSpacing()); m_line_spacing->setEnabled(false); switch (m_theme.lineSpacing()) { case 100: m_line_spacing_type->setCurrentIndex(0); break; case 150: m_line_spacing_type->setCurrentIndex(1); break; case 200: m_line_spacing_type->setCurrentIndex(2); break; default: m_line_spacing->setEnabled(true); break; } connect(m_line_spacing_type, SIGNAL(currentIndexChanged(int)), this, SLOT(lineSpacingChanged(int))); connect(m_line_spacing_type, SIGNAL(currentIndexChanged(int)), this, SLOT(renderPreview())); connect(m_line_spacing, SIGNAL(valueChanged(int)), this, SLOT(renderPreview())); QFormLayout* line_spacing_layout = new QFormLayout(line_spacing); line_spacing_layout->setFieldGrowthPolicy(QFormLayout::FieldsStayAtSizeHint); line_spacing_layout->addRow(tr("Type:"), m_line_spacing_type); line_spacing_layout->addRow(tr("Height:"), m_line_spacing); // Create paragraph spacing group QGroupBox* paragraph_spacing = new QGroupBox(tr("Paragraph Spacing"), contents); m_tab_width = new QSpinBox(paragraph_spacing); m_tab_width->setSuffix(tr(" pixels")); m_tab_width->setRange(theme.tabWidth().minimumValue(), theme.tabWidth().maximumValue()); m_tab_width->setValue(m_theme.tabWidth()); connect(m_tab_width, SIGNAL(valueChanged(int)), this, SLOT(renderPreview())); m_spacing_above_paragraph = new QSpinBox(paragraph_spacing); m_spacing_above_paragraph->setSuffix(tr(" pixels")); m_spacing_above_paragraph->setRange(theme.spacingAboveParagraph().minimumValue(), theme.spacingAboveParagraph().maximumValue()); m_spacing_above_paragraph->setValue(m_theme.spacingAboveParagraph()); connect(m_spacing_above_paragraph, SIGNAL(valueChanged(int)), this, SLOT(renderPreview())); m_spacing_below_paragraph = new QSpinBox(paragraph_spacing); m_spacing_below_paragraph->setSuffix(tr(" pixels")); m_spacing_below_paragraph->setRange(theme.spacingBelowParagraph().minimumValue(), theme.spacingBelowParagraph().maximumValue()); m_spacing_below_paragraph->setValue(m_theme.spacingBelowParagraph()); connect(m_spacing_below_paragraph, SIGNAL(valueChanged(int)), this, SLOT(renderPreview())); m_indent_first_line = new QCheckBox(tr("Indent first line"), paragraph_spacing); m_indent_first_line->setChecked(m_theme.indentFirstLine()); connect(m_indent_first_line, SIGNAL(toggled(bool)), this, SLOT(renderPreview())); QFormLayout* paragraph_spacing_layout = new QFormLayout(paragraph_spacing); paragraph_spacing_layout->setFieldGrowthPolicy(QFormLayout::FieldsStayAtSizeHint); paragraph_spacing_layout->addRow(tr("Tab Width:"), m_tab_width); paragraph_spacing_layout->addRow(tr("Above:"), m_spacing_above_paragraph); paragraph_spacing_layout->addRow(tr("Below:"), m_spacing_below_paragraph); paragraph_spacing_layout->addRow("", m_indent_first_line); // Create preview m_preview_text = new QTextEdit; m_preview_text->setFrameStyle(QFrame::NoFrame); m_preview_text->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); m_preview_text->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); QFile file(":/lorem.txt"); if (file.open(QFile::ReadOnly)) { m_preview_text->setPlainText(QString::fromLatin1(file.readAll())); file.close(); } m_preview = new QLabel(this); m_preview->setAlignment(Qt::AlignCenter); m_preview->setFrameStyle(QFrame::Sunken | QFrame::StyledPanel); QPixmap pixmap(480, 270); pixmap.fill(palette().window().color()); m_preview->setPixmap(pixmap); m_theme_renderer = new ThemeRenderer(this); connect(m_theme_renderer, SIGNAL(rendered(QImage,QRect,Theme)), this, SLOT(renderPreview(QImage,QRect,Theme))); renderPreview(); // Lay out dialog QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, this); m_ok = buttons->button(QDialogButtonBox::Ok); connect(buttons, SIGNAL(accepted()), this, SLOT(accept())); connect(buttons, SIGNAL(rejected()), this, SLOT(reject())); QVBoxLayout* groups_layout = new QVBoxLayout(contents); groups_layout->addWidget(text_group); groups_layout->addWidget(background_group); groups_layout->addWidget(foreground_group); groups_layout->addWidget(m_round_corners); groups_layout->addWidget(m_blur); groups_layout->addWidget(m_shadow); groups_layout->addWidget(margins_group); groups_layout->addWidget(line_spacing); groups_layout->addWidget(paragraph_spacing); QGridLayout* layout = new QGridLayout(this); layout->setColumnStretch(0, 1); layout->setRowStretch(1, 1); layout->setRowMinimumHeight(2, layout->margin()); layout->addLayout(name_layout, 0, 0, 1, 2); layout->addWidget(scroll, 1, 0, 1, 1); layout->addWidget(m_preview, 1, 1, 1, 1, Qt::AlignCenter); layout->addWidget(buttons, 3, 0, 1, 2); resize(QSettings().value("ThemeDialog/Size", sizeHint()).toSize()); }
void ThemeDialog::renderPreview(QImage preview, const QRect& foreground, const Theme& theme) { m_load_color = QtConcurrent::run(averageImage, theme.backgroundImage(), theme.backgroundColor()); // Position preview text int padding = theme.foregroundPadding(); int x = foreground.x() + padding; int y = foreground.y() + padding + theme.spacingAboveParagraph(); int width = foreground.width() - (padding * 2); int height = foreground.height() - (padding * 2) - theme.spacingAboveParagraph(); m_preview_text->setGeometry(x, y, width, height); // Set colors QColor text_color = theme.textColor(); text_color.setAlpha(255); QPalette p = m_preview_text->palette(); p.setBrush(QPalette::Base, preview.copy(x, y, width, height)); p.setColor(QPalette::Text, text_color); p.setColor(QPalette::Highlight, text_color); p.setColor(QPalette::HighlightedText, (qGray(text_color.rgb()) > 127) ? Qt::black : Qt::white); m_preview_text->setPalette(p); // Set spacings int tab_width = theme.tabWidth(); QTextBlockFormat block_format; block_format.setLineHeight(theme.lineSpacing(), (theme.lineSpacing() == 100) ? QTextBlockFormat::SingleHeight : QTextBlockFormat::ProportionalHeight); block_format.setTextIndent(tab_width * theme.indentFirstLine()); block_format.setTopMargin(theme.spacingAboveParagraph()); block_format.setBottomMargin(theme.spacingBelowParagraph()); m_preview_text->textCursor().mergeBlockFormat(block_format); for (int i = 0, count = m_preview_text->document()->allFormats().count(); i < count; ++i) { QTextFormat& f = m_preview_text->document()->allFormats()[i]; if (f.isBlockFormat()) { f.merge(block_format); } } m_preview_text->setTabStopWidth(tab_width); m_preview_text->document()->setIndentWidth(tab_width); // Set font m_preview_text->setFont(theme.textFont()); // Render text m_preview_text->render(&preview, m_preview_text->pos()); // Create zoomed text cutout int x2 = (x >= 24) ? (x - 24) : 0; int y2 = (y >= 24) ? (y - 24) : 0; QImage text_cutout = preview.copy(x2, y2, 162, 110); // Create preview icon m_preview_icon = QImage(":/shadow.png").convertToFormat(QImage::Format_ARGB32_Premultiplied); { QPainter painter(&m_preview_icon); painter.drawImage(9, 9, preview.scaled(240, 135, Qt::KeepAspectRatio, Qt::SmoothTransformation)); painter.fillRect(20, 32, 85, 59, QColor(0, 0, 0, 32)); painter.fillRect(21, 33, 83, 57, Qt::white); int x3 = (x >= 24) ? (x - 12 + theme.tabWidth()) : 12 + theme.tabWidth(); int y3 = (y >= 24) ? (y - 6) : 0; painter.drawImage(22, 34, preview, x3, y3, 81, 55); } // Create preview pixmap preview = preview.scaled(480, 270, Qt::KeepAspectRatio, Qt::SmoothTransformation); { QPainter painter(&preview); painter.setPen(Qt::NoPen); painter.fillRect(22, 46, 170, 118, QColor(0, 0, 0, 32)); painter.fillRect(24, 48, 166, 114, Qt::white); painter.drawImage(26, 50, text_cutout); } m_preview->setPixmap(QPixmap::fromImage(preview)); }