File indexing completed on 2024-11-17 04:42:37

0001 /*
0002   SPDX-FileCopyrightText: 2007 Bruno Virlet <bruno@virlet.org>
0003 
0004   SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0
0005 */
0006 #include "timescaleconfigdialog.h"
0007 #include "prefs.h"
0008 
0009 #include <KCalUtils/Stringify>
0010 
0011 #include <KLocalizedString>
0012 
0013 #include <QDialogButtonBox>
0014 #include <QIcon>
0015 #include <QPushButton>
0016 #include <QTimeZone>
0017 #include <QVBoxLayout>
0018 
0019 using namespace EventViews;
0020 
0021 class EventViews::TimeScaleConfigDialogPrivate
0022 {
0023 public:
0024     TimeScaleConfigDialogPrivate(TimeScaleConfigDialog *parent, const PrefsPtr &preferences)
0025         : q(parent)
0026         , mPreferences(preferences)
0027     {
0028     }
0029 
0030 public:
0031     TimeScaleConfigDialog *const q;
0032     PrefsPtr mPreferences;
0033 };
0034 
0035 enum { TimeZoneNameRole = Qt::UserRole };
0036 
0037 using TimeZoneNamePair = QPair<QString, QByteArray>;
0038 
0039 static QString tzWithUTC(const QByteArray &zoneId)
0040 {
0041     auto tz = QTimeZone(zoneId);
0042     return QStringLiteral("%1 (%2)").arg(i18n(zoneId.constData()), KCalUtils::Stringify::tzUTCOffsetStr(tz));
0043 }
0044 
0045 TimeScaleConfigDialog::TimeScaleConfigDialog(const PrefsPtr &preferences, QWidget *parent)
0046     : QDialog(parent)
0047     , d(new TimeScaleConfigDialogPrivate(this, preferences))
0048 {
0049     setWindowTitle(i18nc("@title:window", "Timezone"));
0050     auto mainLayout = new QVBoxLayout(this);
0051     setModal(true);
0052 
0053     auto mainwidget = new QWidget(this);
0054     setupUi(mainwidget);
0055 
0056     mainLayout->addWidget(mainwidget);
0057 
0058     auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
0059     QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok);
0060     okButton->setDefault(true);
0061     okButton->setShortcut(Qt::CTRL | Qt::Key_Return);
0062     connect(buttonBox, &QDialogButtonBox::rejected, this, &TimeScaleConfigDialog::reject);
0063 
0064     mainLayout->addWidget(buttonBox);
0065 
0066     QStringList shownTimeZones(QString::fromUtf8(d->mPreferences->timeZone().id()));
0067     shownTimeZones += d->mPreferences->timeScaleTimezones();
0068     shownTimeZones.removeDuplicates();
0069 
0070     QList<TimeZoneNamePair> availList;
0071     QList<TimeZoneNamePair> selList;
0072     const auto zoneIds = QTimeZone::availableTimeZoneIds();
0073     for (const auto &zoneId : std::as_const(zoneIds)) {
0074         // do not list timezones already shown
0075         if (!shownTimeZones.contains(QString::fromUtf8(zoneId))) {
0076             availList.append(TimeZoneNamePair(tzWithUTC(zoneId), zoneId));
0077         } else {
0078             selList.append(TimeZoneNamePair(tzWithUTC(zoneId), zoneId));
0079         }
0080     }
0081     std::sort(availList.begin(), availList.end());
0082 
0083     for (const TimeZoneNamePair &item : std::as_const(availList)) {
0084         zoneCombo->addItem(item.first, item.second);
0085     }
0086     zoneCombo->setCurrentIndex(0);
0087 
0088     addButton->setIcon(QIcon::fromTheme(QStringLiteral("list-add")));
0089     removeButton->setIcon(QIcon::fromTheme(QStringLiteral("list-remove")));
0090     upButton->setIcon(QIcon::fromTheme(QStringLiteral("go-up")));
0091     downButton->setIcon(QIcon::fromTheme(QStringLiteral("go-down")));
0092 
0093     connect(addButton, &QPushButton::clicked, this, &TimeScaleConfigDialog::add);
0094     connect(removeButton, &QPushButton::clicked, this, &TimeScaleConfigDialog::remove);
0095     connect(upButton, &QPushButton::clicked, this, &TimeScaleConfigDialog::up);
0096     connect(downButton, &QPushButton::clicked, this, &TimeScaleConfigDialog::down);
0097 
0098     connect(okButton, &QPushButton::clicked, this, &TimeScaleConfigDialog::okClicked);
0099     connect(buttonBox->button(QDialogButtonBox::Cancel), &QPushButton::clicked, this, &TimeScaleConfigDialog::reject);
0100     connect(listWidget, &QListWidget::currentItemChanged, this, &TimeScaleConfigDialog::slotUpdateButton);
0101 
0102     for (const TimeZoneNamePair &item : std::as_const(selList)) {
0103         auto widgetItem = new QListWidgetItem(item.first);
0104         widgetItem->setData(TimeZoneNameRole, item.second);
0105         listWidget->addItem(widgetItem);
0106     }
0107     slotUpdateButton();
0108 }
0109 
0110 TimeScaleConfigDialog::~TimeScaleConfigDialog() = default;
0111 
0112 void TimeScaleConfigDialog::slotUpdateButton()
0113 {
0114     removeButton->setEnabled(listWidget->currentItem());
0115     const bool numberElementMoreThanOneElement = (listWidget->count() > 1);
0116     upButton->setEnabled(numberElementMoreThanOneElement && (listWidget->currentRow() >= 1));
0117     downButton->setEnabled(numberElementMoreThanOneElement && (listWidget->currentRow() < listWidget->count() - 1));
0118 }
0119 
0120 void TimeScaleConfigDialog::okClicked()
0121 {
0122     d->mPreferences->setTimeScaleTimezones(zones());
0123     d->mPreferences->writeConfig();
0124     accept();
0125 }
0126 
0127 void TimeScaleConfigDialog::add()
0128 {
0129     // Do not add duplicates
0130     if (zoneCombo->currentIndex() >= 0) {
0131         const int numberItem(listWidget->count());
0132         for (int i = 0; i < numberItem; ++i) {
0133             if (listWidget->item(i)->data(TimeZoneNameRole).toString() == zoneCombo->itemData(zoneCombo->currentIndex(), TimeZoneNameRole).toString()) {
0134                 return;
0135             }
0136         }
0137 
0138         auto item = new QListWidgetItem(zoneCombo->currentText());
0139         item->setData(TimeZoneNameRole, zoneCombo->itemData(zoneCombo->currentIndex(), TimeZoneNameRole).toString());
0140         listWidget->addItem(item);
0141         zoneCombo->removeItem(zoneCombo->currentIndex());
0142     }
0143     slotUpdateButton();
0144 }
0145 
0146 void TimeScaleConfigDialog::remove()
0147 {
0148     zoneCombo->insertItem(0, listWidget->currentItem()->text(), zoneCombo->itemData(zoneCombo->currentIndex(), TimeZoneNameRole).toString());
0149     delete listWidget->takeItem(listWidget->currentRow());
0150     slotUpdateButton();
0151 }
0152 
0153 void TimeScaleConfigDialog::up()
0154 {
0155     int row = listWidget->currentRow();
0156     QListWidgetItem *item = listWidget->takeItem(row);
0157     listWidget->insertItem(qMax(row - 1, 0), item);
0158     listWidget->setCurrentRow(qMax(row - 1, 0));
0159 }
0160 
0161 void TimeScaleConfigDialog::down()
0162 {
0163     int row = listWidget->currentRow();
0164     QListWidgetItem *item = listWidget->takeItem(row);
0165     listWidget->insertItem(qMin(row + 1, listWidget->count()), item);
0166     listWidget->setCurrentRow(qMin(row + 1, listWidget->count() - 1));
0167 }
0168 
0169 QStringList TimeScaleConfigDialog::zones() const
0170 {
0171     QStringList list;
0172     const int count = listWidget->count();
0173     list.reserve(count);
0174     for (int i = 0; i < count; ++i) {
0175         list << listWidget->item(i)->data(TimeZoneNameRole).toString();
0176     }
0177     return list;
0178 }
0179 
0180 #include "moc_timescaleconfigdialog.cpp"