File indexing completed on 2024-12-01 11:10:30

0001 /*
0002     SPDX-FileCopyrightText: 2020 Michail Vourlakos <mvourlakos@gmail.com>
0003     SPDX-License-Identifier: GPL-2.0-or-later
0004 */
0005 
0006 #include "detailshandler.h"
0007 
0008 // local
0009 #include "ui_detailsdialog.h"
0010 #include "colorsmodel.h"
0011 #include "detailsdialog.h"
0012 #include "patternwidget.h"
0013 #include "schemesmodel.h"
0014 #include "delegates/colorcmbitemdelegate.h"
0015 #include "delegates/schemecmbitemdelegate.h"
0016 #include "../settingsdialog/layoutscontroller.h"
0017 #include "../settingsdialog/layoutsmodel.h"
0018 #include "../settingsdialog/delegates/layoutcmbitemdelegate.h"
0019 #include "../../data/layoutstable.h"
0020 #include "../../layout/abstractlayout.h"
0021 
0022 // Qt
0023 #include <QColorDialog>
0024 #include <QFileDialog>
0025 #include <QIcon>
0026 
0027 // KDE
0028 #include <KIconDialog>
0029 
0030 namespace Latte {
0031 namespace Settings {
0032 namespace Handler {
0033 
0034 DetailsHandler::DetailsHandler(Dialog::DetailsDialog *dialog)
0035     : Generic(dialog),
0036       m_dialog(dialog),
0037       m_ui(m_dialog->ui()),
0038       m_colorsModel(new Model::Colors(this, dialog->corona())),
0039       m_schemesModel(new Model::Schemes(this))
0040 {
0041     init();
0042 }
0043 
0044 DetailsHandler::~DetailsHandler()
0045 {
0046 }
0047 
0048 void DetailsHandler::init()
0049 {
0050     //! Layouts
0051     m_layoutsProxyModel = new QSortFilterProxyModel(this);
0052     m_layoutsProxyModel->setSourceModel(m_dialog->layoutsController()->baseModel());
0053     m_layoutsProxyModel->setSortRole(Model::Layouts::SORTINGROLE);
0054     m_layoutsProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
0055     m_layoutsProxyModel->sort(Model::Layouts::NAMECOLUMN, Qt::AscendingOrder);
0056 
0057     m_ui->layoutsCmb->setModel(m_layoutsProxyModel);
0058     m_ui->layoutsCmb->setModelColumn(Model::Layouts::NAMECOLUMN);
0059     m_ui->layoutsCmb->setItemDelegate(new Settings::Layout::Delegate::LayoutCmbItemDelegate(this));
0060 
0061     //! Schemes
0062     m_ui->customSchemeCmb->setModel(m_schemesModel);
0063     m_ui->customSchemeCmb->setItemDelegate(new Settings::Details::Delegate::SchemeCmbItemDelegate(this));
0064 
0065     //! Background Pattern
0066     m_backButtonsGroup = new QButtonGroup(this);
0067     m_backButtonsGroup->addButton(m_ui->colorRadioBtn, Latte::Layout::ColorBackgroundStyle);
0068     m_backButtonsGroup->addButton(m_ui->backRadioBtn, Latte::Layout::PatternBackgroundStyle);
0069     m_backButtonsGroup->setExclusive(true);
0070 
0071     m_ui->colorsCmb->setItemDelegate(new Details::Delegate::ColorCmbBoxItem(this));
0072     m_ui->colorsCmb->setModel(m_colorsModel);
0073 
0074     m_ui->patternClearBtn->setFixedHeight(m_ui->backgroundBtn->height()+2);
0075 
0076     connect(m_backButtonsGroup, static_cast<void(QButtonGroup::*)(int, bool)>(&QButtonGroup::buttonToggled),
0077             [ = ](int id, bool checked) {
0078 
0079         if (checked) {
0080             setBackgroundStyle(static_cast<Latte::Layout::BackgroundStyle>(id));
0081         }
0082     });
0083 
0084     connect(m_ui->backgroundBtn, &QPushButton::pressed, this, &DetailsHandler::selectBackground);
0085     connect(m_ui->iconBtn, &QPushButton::pressed, this, &DetailsHandler::selectIcon);
0086     connect(m_ui->iconClearBtn, &QPushButton::pressed, this, &DetailsHandler::clearIcon);
0087     connect(m_ui->textColorBtn, &QPushButton::pressed, this, &DetailsHandler::selectTextColor);
0088     connect(m_ui->patternClearBtn, &QPushButton::pressed, this, &DetailsHandler::clearPattern);
0089 
0090 
0091     //! Options
0092     connect(m_ui->popUpMarginSpinBox, qOverload<int>(&QSpinBox::valueChanged), this, [&](int i) {
0093         setPopUpMargin(i);
0094     });
0095 
0096     connect(m_ui->inMenuChk, &QCheckBox::stateChanged, this, [&]() {
0097         setIsShownInMenu(m_ui->inMenuChk->isChecked());
0098     });
0099 
0100     connect(m_ui->borderlessChk, &QCheckBox::stateChanged, this, [&]() {
0101         setHasDisabledBorders(m_ui->borderlessChk->isChecked());
0102     });
0103 
0104     connect(this, &DetailsHandler::currentLayoutChanged, this, &DetailsHandler::reload);
0105 
0106     reload();
0107     m_lastConfirmedLayoutIndex = m_ui->colorsCmb->currentIndex();
0108 
0109     //! connect layout combobox after the selected layout has been loaded
0110     connect(m_ui->layoutsCmb, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &DetailsHandler::onCurrentLayoutIndexChanged);
0111 
0112     //! connect colors combobox after the selected layout has been loaded
0113     connect(m_ui->colorsCmb, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &DetailsHandler::onCurrentColorIndexChanged);
0114 
0115     //! connect custom scheme combobox after the selected layout has been loaded
0116     connect(m_ui->customSchemeCmb, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &DetailsHandler::onCurrentSchemeIndexChanged);
0117 
0118     //! pattern widgets
0119     connect(m_ui->backPatternWidget, &Widget::PatternWidget::mouseReleased, this, [&]() {
0120         setBackgroundStyle(Latte::Layout::PatternBackgroundStyle);
0121     });
0122     connect(m_ui->colorPatternWidget, &Widget::PatternWidget::mouseReleased, this, [&]() {
0123         setBackgroundStyle(Latte::Layout::ColorBackgroundStyle);
0124     });
0125 
0126 
0127     //! data were changed
0128     connect(this, &DetailsHandler::dataChanged, this, [&]() {
0129         loadLayout(c_data);
0130     });
0131 }
0132 
0133 void DetailsHandler::reload()
0134 {
0135     o_data = m_dialog->layoutsController()->selectedLayoutCurrentData();
0136     c_data = o_data;
0137 
0138     Latte::Data::LayoutIcon icon = m_dialog->layoutsController()->selectedLayoutIcon();
0139 
0140     m_ui->layoutsCmb->setCurrentText(o_data.name);
0141     m_ui->layoutsCmb->setLayoutIcon(icon);
0142 
0143     loadLayout(c_data);
0144 }
0145 
0146 void DetailsHandler::loadLayout(const Latte::Data::Layout &data)
0147 {
0148     if (data.icon.isEmpty()) {
0149         m_ui->iconBtn->setIcon(QIcon::fromTheme("add"));
0150         m_ui->iconClearBtn->setVisible(false);
0151     } else {
0152         m_ui->iconBtn->setIcon(QIcon::fromTheme(data.icon));
0153         m_ui->iconClearBtn->setVisible(true);
0154     }
0155 
0156     if (data.backgroundStyle == Latte::Layout::ColorBackgroundStyle) {
0157         m_ui->colorRadioBtn->setChecked(true);
0158         m_ui->backRadioBtn->setChecked(false);
0159 
0160         m_ui->colorsCmb->setVisible(true);
0161         m_ui->backgroundBtn->setVisible(false);
0162         m_ui->textColorBtn->setVisible(false);
0163         m_ui->patternClearBtn->setVisible(false);
0164     } else {
0165         m_ui->colorRadioBtn->setChecked(false);
0166         m_ui->backRadioBtn->setChecked(true);
0167 
0168         m_ui->colorsCmb->setVisible(false);
0169         m_ui->backgroundBtn->setVisible(true);
0170         m_ui->textColorBtn->setVisible(true);
0171         m_ui->patternClearBtn->setVisible(true);
0172     }
0173 
0174     int schind = m_schemesModel->row(data.schemeFile);
0175     m_ui->customSchemeCmb->setCurrentIndex(schind);
0176     updateCustomSchemeCmb(schind);
0177 
0178     m_ui->colorPatternWidget->setBackground(m_colorsModel->colorPath(data.color));
0179     m_ui->colorPatternWidget->setTextColor(Latte::Layout::AbstractLayout::defaultTextColor(data.color));
0180 
0181     m_ui->colorsCmb->setCurrentIndex(m_colorsModel->row(data.color));
0182 
0183     if (data.background.isEmpty()) {
0184         m_ui->backPatternWidget->setBackground(m_colorsModel->colorPath(Latte::Layout::AbstractLayout::defaultCustomBackground()));
0185     } else {
0186         m_ui->backPatternWidget->setBackground(data.background);
0187     }
0188 
0189     if (data.background.isEmpty() && data.textColor.isEmpty()) {
0190         m_ui->backPatternWidget->setTextColor(Latte::Layout::AbstractLayout::defaultCustomTextColor());
0191     } else {
0192         m_ui->backPatternWidget->setTextColor(data.textColor);
0193     }
0194 
0195     if (!data.background.isEmpty() || !data.textColor.isEmpty()) {
0196         m_ui->patternClearBtn->setEnabled(true);
0197     } else {
0198         m_ui->patternClearBtn->setEnabled(false);
0199     }
0200 
0201     m_ui->popUpMarginSpinBox->setValue(data.popUpMargin);
0202 
0203     m_ui->inMenuChk->setChecked(data.isShownInMenu);
0204     m_ui->borderlessChk->setChecked(data.hasDisabledBorders);
0205 
0206     updateWindowTitle();
0207 }
0208 
0209 Latte::Data::Layout DetailsHandler::currentData() const
0210 {
0211     return c_data;
0212 }
0213 
0214 bool DetailsHandler::hasChangedData() const
0215 {
0216     return o_data != c_data;
0217 }
0218 
0219 bool DetailsHandler::inDefaultValues() const
0220 {
0221     //nothing special
0222     return true;
0223 }
0224 
0225 
0226 void DetailsHandler::reset()
0227 {
0228     c_data = o_data;
0229     emit currentLayoutChanged();
0230 }
0231 
0232 void DetailsHandler::resetDefaults()
0233 {
0234     //do nothing
0235 }
0236 
0237 void DetailsHandler::save()
0238 {
0239     m_dialog->layoutsController()->setLayoutProperties(currentData());
0240 }
0241 
0242 void DetailsHandler::clearIcon()
0243 {
0244     setIcon("");
0245 }
0246 
0247 void DetailsHandler::clearPattern()
0248 {
0249     setBackground("");
0250     setTextColor("");
0251 }
0252 
0253 void DetailsHandler::onCurrentColorIndexChanged(int row)
0254 {
0255     QString selectedColor = m_ui->colorsCmb->itemData(row, Model::Colors::IDROLE).toString();
0256     setColor(selectedColor);
0257 }
0258 
0259 void DetailsHandler::onCurrentLayoutIndexChanged(int row)
0260 {
0261     bool switchtonewlayout{false};
0262 
0263     if (m_lastConfirmedLayoutIndex != row) {
0264         if (hasChangedData()) { //new layout was chosen but there are changes
0265             KMessageBox::ButtonCode result = saveChangesConfirmation();
0266 
0267             if (result == KMessageBox::Yes) {
0268                 switchtonewlayout = true;
0269                 m_lastConfirmedLayoutIndex = row;
0270                 save();
0271             } else if (result == KMessageBox::No) {
0272                 switchtonewlayout = true;
0273                 m_lastConfirmedLayoutIndex = row;
0274             } else if (result == KMessageBox::Cancel) {
0275                 //do nothing
0276             }
0277         } else { //new layout was chosen and there are no changes
0278             switchtonewlayout = true;
0279             m_lastConfirmedLayoutIndex = row;
0280         }
0281     }
0282 
0283     if (switchtonewlayout) {
0284         QString layoutId = m_layoutsProxyModel->data(m_layoutsProxyModel->index(row, Model::Layouts::IDCOLUMN), Qt::UserRole).toString();
0285         m_dialog->layoutsController()->selectRow(layoutId);
0286         reload();
0287         emit currentLayoutChanged();
0288     } else {
0289         //! reset combobox index
0290         m_ui->layoutsCmb->setCurrentText(c_data.name);
0291     }
0292 }
0293 
0294 void DetailsHandler::updateCustomSchemeCmb(const int &row)
0295 {
0296     int scmind = row;
0297     m_ui->customSchemeCmb->setCurrentText(m_ui->customSchemeCmb->itemData(scmind, Qt::DisplayRole).toString());
0298     m_ui->customSchemeCmb->setTextColor(m_ui->customSchemeCmb->itemData(scmind, Model::Schemes::TEXTCOLORROLE).value<QColor>());
0299     m_ui->customSchemeCmb->setBackgroundColor(m_ui->customSchemeCmb->itemData(scmind, Model::Schemes::BACKGROUNDCOLORROLE).value<QColor>());
0300 }
0301 
0302 void DetailsHandler::onCurrentSchemeIndexChanged(int row)
0303 {
0304     updateCustomSchemeCmb(row);
0305     QString selectedScheme = m_ui->customSchemeCmb->itemData(row, Model::Schemes::IDROLE).toString();
0306     setCustomSchemeFile(selectedScheme);
0307 }
0308 
0309 void DetailsHandler::setBackground(const QString &background)
0310 {
0311     if (c_data.background == background) {
0312         return;
0313     }
0314 
0315     c_data.background = background;
0316     emit dataChanged();
0317 }
0318 
0319 void DetailsHandler::setColor(const QString &color)
0320 {
0321     if (c_data.color == color) {
0322         return;
0323     }
0324 
0325     c_data.color = color;
0326     emit dataChanged();
0327 }
0328 
0329 void DetailsHandler::setCustomSchemeFile(const QString &file)
0330 {
0331     if (c_data.schemeFile == file) {
0332         return;
0333     }
0334 
0335     c_data.schemeFile = file;
0336     emit dataChanged();
0337 }
0338 
0339 void DetailsHandler::setIcon(const QString &icon)
0340 {
0341     if (c_data.icon == icon) {
0342         return;
0343     }
0344 
0345     c_data.icon = icon;
0346     emit dataChanged();
0347 }
0348 
0349 void DetailsHandler::setTextColor(const QString &textColor)
0350 {
0351     if (c_data.textColor == textColor) {
0352         return;
0353     }
0354 
0355     c_data.textColor = textColor;
0356     emit dataChanged();
0357 }
0358 
0359 void DetailsHandler::setIsShownInMenu(bool inMenu)
0360 {
0361     if (c_data.isShownInMenu == inMenu) {
0362         return;
0363     }
0364 
0365     c_data.isShownInMenu = inMenu;
0366     emit dataChanged();
0367 }
0368 
0369 void DetailsHandler::setHasDisabledBorders(bool disabled)
0370 {
0371     if (c_data.hasDisabledBorders == disabled) {
0372         return;
0373     }
0374 
0375     c_data.hasDisabledBorders = disabled;
0376     emit dataChanged();
0377 }
0378 
0379 void DetailsHandler::setBackgroundStyle(const Latte::Layout::BackgroundStyle &style)
0380 {
0381     if (c_data.backgroundStyle == style) {
0382         return;
0383     }
0384 
0385     c_data.backgroundStyle = style;
0386     emit dataChanged();
0387 }
0388 
0389 void DetailsHandler::setPopUpMargin(const int &margin)
0390 {
0391     if (c_data.popUpMargin == margin) {
0392         return;
0393     }
0394 
0395     c_data.popUpMargin = margin;
0396     emit dataChanged();
0397 }
0398 
0399 void DetailsHandler::selectBackground()
0400 {
0401     QStringList mimeTypeFilters;
0402     mimeTypeFilters << "image/jpeg" // will show "JPEG image (*.jpeg *.jpg)
0403                     << "image/png";  // will show "PNG image (*.png)"
0404 
0405     QFileDialog dialog(m_dialog);
0406     dialog.setMimeTypeFilters(mimeTypeFilters);
0407 
0408     QString background =  m_ui->backPatternWidget->background();
0409 
0410     if (background.startsWith("/") && QFileInfo(background).exists()) {
0411         dialog.setDirectory(QFileInfo(background).absolutePath());
0412         dialog.selectFile(background);
0413     }
0414 
0415     if (dialog.exec()) {
0416         QStringList files = dialog.selectedFiles();
0417 
0418         if (files.count() > 0) {
0419             setBackground(files[0]);
0420         }
0421     }
0422 }
0423 
0424 void DetailsHandler::selectIcon()
0425 {
0426     QString icon = KIconDialog::getIcon();
0427 
0428     if (!icon.isEmpty()) {
0429         setIcon(icon);
0430     }
0431 }
0432 
0433 void DetailsHandler::selectTextColor()
0434 {
0435     QColorDialog dialog(m_dialog);
0436     dialog.setCurrentColor(QColor(m_ui->backPatternWidget->textColor()));
0437 
0438     if (dialog.exec()) {
0439         qDebug() << "layout selected text color: " << dialog.selectedColor().name();
0440         setTextColor(dialog.selectedColor().name());
0441     }
0442 }
0443 
0444 void DetailsHandler::updateWindowTitle()
0445 {
0446     m_dialog->setWindowTitle(i18nc("<layout name> Details","%1 Details", m_ui->layoutsCmb->currentText()));
0447 }
0448 
0449 KMessageBox::ButtonCode DetailsHandler::saveChangesConfirmation()
0450 {
0451     if (hasChangedData()) {
0452         QString layoutName = c_data.name;
0453         QString saveChangesText = i18n("The settings of <b>%1</b> layout have changed.<br/>Do you want to apply the changes or discard them?", layoutName);
0454 
0455         return m_dialog->saveChangesConfirmation(saveChangesText);
0456     }
0457 
0458     return KMessageBox::Cancel;
0459 }
0460 
0461 }
0462 }
0463 }