[pim/korganizer] plugins/lunarphases: lunarphases - add configuration for northern vs. southern hemipshere

Allen Winter <[email protected]>
Newsgroups gmane.comp.kde.cvs
Message-ID <[email protected]>
Git commit 34b5f52bfa01ef85ab5d87465fb03f1ca0a5aafe by Allen Winter.
Committed on 05/08/2026 at 20:01.
Pushed by winterz into branch 'master'.

lunarphases - add configuration for northern vs. southern hemipshere

Lunar phases depend on the hemisphere

M  +2    -0    plugins/lunarphases/CMakeLists.txt
A  +90   -0    plugins/lunarphases/configdialog.cpp     [License: GPL(v2.0+)]
A  +31   -0    plugins/lunarphases/configdialog.h     [License: GPL(v2.0+)]
M  +14   -16   plugins/lunarphases/lunarphases.cpp
M  +11   -1    plugins/lunarphases/lunarphases.h
M  +1    -1    plugins/lunarphases/lunarphases.json

https://invent.kde.org/pim/korganizer/-/commit/34b5f52bfa01ef85ab5d87465fb03f1ca0a5aafe

diff --git a/plugins/lunarphases/CMakeLists.txt b/plugins/lunarphases/CMakeLists.txt
index 99dec6e9f..fda46de14 100644
--- a/plugins/lunarphases/CMakeLists.txt
+++ b/plugins/lunarphases/CMakeLists.txt
@@ -6,6 +6,8 @@
 add_library(
     lunarphases
     MODULE
+    configdialog.cpp
+    configdialog.h
     lunarphases.cpp
     lunarphases.h
 )
diff --git a/plugins/lunarphases/configdialog.cpp b/plugins/lunarphases/configdialog.cpp
new file mode 100644
index 000000000..a6a935489
--- /dev/null
+++ b/plugins/lunarphases/configdialog.cpp
@@ -0,0 +1,90 @@
+/*
+  This file is part of KOrganizer.
+
+  SPDX-FileCopyrightText: Allen Winter <[email protected]>
+  SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+#include "configdialog.h"
+#include "lunarphases.h"
+
+#include <KConfig>
+#include <KLocalizedString>
+
+#include <KConfigGroup>
+#include <QButtonGroup>
+#include <QDialogButtonBox>
+#include <QGroupBox>
+#include <QPushButton>
+#include <QRadioButton>
+#include <QVBoxLayout>
+
+ConfigDialog::ConfigDialog(QWidget *parent)
+    : QDialog(parent)
+    , mLunarPhaseGroup(new QButtonGroup(this))
+{
+    setWindowTitle(i18nc("@title:window", "Configure Lunar Phases"));
+    auto mainLayout = new QVBoxLayout(this);
+    auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
+    QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok);
+    okButton->setShortcut(Qt::CTRL | Qt::Key_Return);
+    connect(buttonBox, &QDialogButtonBox::rejected, this, &ConfigDialog::reject);
+    okButton->setDefault(true);
+    setModal(true);
+    auto topFrame = new QFrame(this);
+    mainLayout->addWidget(topFrame);
+    mainLayout->addStretch(1);
+    mainLayout->addWidget(buttonBox);
+    auto topLayout = new QVBoxLayout(topFrame);
+    topLayout->setContentsMargins({});
+
+    auto lunarPhaseBox = new QGroupBox(i18nc("@title:group", "Choose your hemisphere"), topFrame);
+    lunarPhaseBox->setFlat(true);
+    topLayout->addWidget(lunarPhaseBox);
+    auto groupLayout = new QVBoxLayout(lunarPhaseBox);
+
+    auto btn = new QRadioButton(i18nc("@option:radio", "Northern Hemisphere"), lunarPhaseBox);
+    btn->setToolTip(i18nc("@info:tooltip", "Show the lunar phases for the northern hemisphere"));
+    btn->setWhatsThis(i18nc("@info:whatsthis", "Select this option to show the moon phases if you live in the northern hemisphere."));
+    mLunarPhaseGroup->addButton(btn, int(Lunarphases::NorthernHemisphere));
+    groupLayout->addWidget(btn);
+    btn = new QRadioButton(i18nc("@option:radio", "Southern Hemisphere"), lunarPhaseBox);
+    btn->setToolTip(i18nc("@info:tooltip", "Show the lunar phases for the northern hemisphere"));
+    btn->setWhatsThis(i18nc("@info:whatsthis", "Select this option to show the moon phases if you live in the southern hemisphere."));
+    mLunarPhaseGroup->addButton(btn, int(Lunarphases::SouthernHemisphere));
+    groupLayout->addWidget(btn);
+
+    connect(okButton, &QPushButton::clicked, this, &ConfigDialog::slotOk);
+
+    load();
+}
+
+ConfigDialog::~ConfigDialog() = default;
+
+void ConfigDialog::load()
+{
+    KConfig _config(QStringLiteral("korganizerrc"), KConfig::NoGlobals);
+    KConfigGroup const config(&_config, QStringLiteral("Calendar/Lunar Phases Plugin"));
+    int const hemisphere = config.readEntry("Hemisphere", int(Lunarphases::NorthernHemisphere));
+    QAbstractButton *btn = mLunarPhaseGroup->button(hemisphere);
+    if (!btn) {
+        btn = mLunarPhaseGroup->button(int(Lunarphases::NorthernHemisphere));
+    }
+    btn->setChecked(true);
+}
+
+void ConfigDialog::save()
+{
+    KConfig _config(QStringLiteral("korganizerrc"), KConfig::NoGlobals);
+    KConfigGroup config(&_config, QStringLiteral("Calendar/Lunar Phases Plugin"));
+    config.writeEntry("Hemisphere", mLunarPhaseGroup->checkedId());
+    config.sync();
+}
+
+void ConfigDialog::slotOk()
+{
+    save();
+    accept();
+}
+
+#include "moc_configdialog.cpp"
diff --git a/plugins/lunarphases/configdialog.h b/plugins/lunarphases/configdialog.h
new file mode 100644
index 000000000..c6ddefc6e
--- /dev/null
+++ b/plugins/lunarphases/configdialog.h
@@ -0,0 +1,31 @@
+/*
+  This file is part of KOrganizer.
+
+  SPDX-FileCopyrightText: Allen Winter <[email protected]>
+  SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+#pragma once
+
+#include <QDialog>
+
+class QButtonGroup;
+
+class ConfigDialog : public QDialog
+{
+    Q_OBJECT
+
+public:
+    explicit ConfigDialog(QWidget *parent = nullptr);
+    ~ConfigDialog() override;
+
+protected:
+    void load();
+    void save();
+
+protected Q_SLOTS:
+    void slotOk();
+
+private:
+    QButtonGroup *const mLunarPhaseGroup;
+};
diff --git a/plugins/lunarphases/lunarphases.cpp b/plugins/lunarphases/lunarphases.cpp
index a54736d7c..11adcad8a 100644
--- a/plugins/lunarphases/lunarphases.cpp
+++ b/plugins/lunarphases/lunarphases.cpp
@@ -6,6 +6,7 @@
 */
 
 #include "lunarphases.h"
+#include "configdialog.h"
 
 #include <KConfig>
 #include <KConfigGroup>
@@ -14,15 +15,7 @@
 
 K_PLUGIN_CLASS_WITH_JSON(Lunarphases, "lunarphases.json")
 
-namespace
-{
-enum Hemisphere {
-    NorthernHemisphere,
-    SouthernHemisphere,
-};
-}
-
-static QIcon phaseIcon(KHolidays::LunarPhase::Phase phase, Hemisphere hemisphere)
+static QIcon phaseIcon(KHolidays::LunarPhase::Phase phase, Lunarphases::Hemisphere hemisphere)
 {
     QString iconName;
     switch (phase) {
@@ -54,7 +47,7 @@ static QIcon phaseIcon(KHolidays::LunarPhase::Phase phase, Hemisphere hemisphere
         break;
     }
     if (iconName != QStringLiteral("moon-new") && iconName != QStringLiteral("moon-full")) {
-        if (hemisphere == Hemisphere::NorthernHemisphere) {
+        if (hemisphere == Lunarphases::NorthernHemisphere) {
             iconName += QStringLiteral("-north");
         } else {
             iconName += QStringLiteral("-south");
@@ -63,11 +56,10 @@ static QIcon phaseIcon(KHolidays::LunarPhase::Phase phase, Hemisphere hemisphere
     return iconName.isEmpty() ? QIcon() : QIcon::fromTheme(iconName);
 }
 
-LunarphasesElement::LunarphasesElement(KHolidays::LunarPhase::Phase phase)
+LunarphasesElement::LunarphasesElement(KHolidays::LunarPhase::Phase phase, Lunarphases::Hemisphere hemisphere)
     : Element(QStringLiteral("main element"))
     , mName(KHolidays::LunarPhase::phaseName(phase))
-    , mIcon(phaseIcon(phase, Hemisphere::NorthernHemisphere)) // TODO: handle southern hemisphere
-
+    , mIcon(phaseIcon(phase, hemisphere))
 {
 }
 
@@ -91,14 +83,20 @@ Lunarphases::Lunarphases(QObject *parent, const QVariantList &args)
 {
     KConfig _config(QStringLiteral("korganizerrc"));
     KConfigGroup const config(&_config, QStringLiteral("Calendar/Lunar Phases Plugin"));
+    mHemisphere = (Hemisphere)config.readEntry("Hemisphere", int(NorthernHemisphere));
+}
+
+void Lunarphases::configure(QWidget *parent)
+{
+    ConfigDialog dlg(parent);
+    dlg.exec();
 }
 
 QString Lunarphases::info() const
 {
     return i18n(
         "This plugin displays the day's lunar phase (New, First, Last, Full). "
-        "Currently, the phase is computed for noon at UTC; therefore, you should "
-        "expect variations by 1 day in either direction.");
+        "The phase is computed for noon in the system timezone.");
 }
 
 Element::List Lunarphases::createDayElements(const QDate &date)
@@ -107,7 +105,7 @@ Element::List Lunarphases::createDayElements(const QDate &date)
 
     KHolidays::LunarPhase::Phase const phase = KHolidays::LunarPhase::phaseAtDate(date);
     if (phase != KHolidays::LunarPhase::None) {
-        auto e = new LunarphasesElement(phase);
+        auto e = new LunarphasesElement(phase, mHemisphere);
         result.append(e);
     }
 
diff --git a/plugins/lunarphases/lunarphases.h b/plugins/lunarphases/lunarphases.h
index 8f8859bea..6727ee362 100644
--- a/plugins/lunarphases/lunarphases.h
+++ b/plugins/lunarphases/lunarphases.h
@@ -14,11 +14,21 @@ using namespace EventViews::CalendarDecoration;
 class Lunarphases : public Decoration
 {
 public:
+    enum Hemisphere {
+        NorthernHemisphere,
+        SouthernHemisphere,
+    };
+    Q_DECLARE_FLAGS(Hemispheres, Hemisphere)
+
     explicit Lunarphases(QObject *parent = nullptr, const QVariantList &args = {});
+    void configure(QWidget *parent) override;
 
     [[nodiscard]] Element::List createDayElements(const QDate &) override;
 
     [[nodiscard]] QString info() const override;
+
+private:
+    Hemisphere mHemisphere;
 };
 
 class LunarphasesElement : public Element
@@ -26,7 +36,7 @@ class LunarphasesElement : public Element
     Q_OBJECT
 
 public:
-    explicit LunarphasesElement(KHolidays::LunarPhase::Phase phase);
+    explicit LunarphasesElement(KHolidays::LunarPhase::Phase phase, Lunarphases::Hemisphere hemisphere);
 
     [[nodiscard]] QString shortText() const override;
     [[nodiscard]] QString longText() const override;
diff --git a/plugins/lunarphases/lunarphases.json b/plugins/lunarphases/lunarphases.json
index 0b67121fe..c6bdc52c7 100644
--- a/plugins/lunarphases/lunarphases.json
+++ b/plugins/lunarphases/lunarphases.json
@@ -50,6 +50,6 @@
         "Name[tr]": "Ay’ın Evreleri",
         "Name[uk]": "Фази Місяця"
     },
-    "X-KDE-KOrganizer-HasSettings": false,
+    "X-KDE-KOrganizer-HasSettings": true,
     "X-KDE-PluginInterfaceVersion": 2
 }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.