Zren / plasma-applets

This monolithic repo has been broken up into individual repos for each widget.
84 stars 23 forks source link

Week Numbers in agenda #19

Open Zren opened 8 years ago

Zren commented 8 years ago

http://kde-look.org/content/show.php?content=175591&forumpage=2#c487350

matty-r commented 3 years ago

@Zren I've been looking through the code the last couple days, because i'd like to tackle this enhancement request. I've been getting pretty confused on way the qml files are all linked together.

Example below on what I want to achieve. The idea being that the current viewed week would always be the top line, and then a separate week line for each subsequent week. I've tried calling back from AgendaModel.buildAgendaItem(), and adding a week property in there, getting the week number from MonthView.calendarBackend. But I can't seem to follow how to access the properties from within AgendaModel.

Obviously i'm very new at this QML/Qt stuff so some pointers would be helpful. Thanks mate.

Mock up: image

Zren commented 3 years ago

While testing QQC2.ScrollView with ListView, I remembered the ListView has section headers. Appearently it can also stay fixed to the top too. It's drawn on top though. We'd need to find a way to mask the items underneath.

I used to use ListView, however it had really bad scrolling lag. Here's how to enable it though:

https://github.com/Zren/plasma-applet-eventcalendar/compare/scrollview2

And here's a quick QML mockup:

// test.qml
// Run: qmlscene test.qml
import QtQuick 2.0
import QtQuick.Window 2.0
import QtQuick.Controls 1.0 as QQC1
import QtQuick.Controls 2.2 as QQC2

Window {
    width: 600
    height: 800

    ListModel {
        id: listModel
    }
    Timer {
        repeat: true
        running: true
        interval: 100
        onTriggered: {
            var t = Date.now()
            var d = Math.floor(t / 1000)
            listModel.insert(0, {
                t: t,
                d: d,
            })
            listModel.append({
                t: t,
                d: d,
            })
        }
    }

    QQC2.ScrollView {
        anchors.fill: parent
        QQC2.ScrollBar.horizontal.policy: QQC2.ScrollBar.AlwaysOff

        ListView {
            id: listView
            model: listModel
            section.property: 'd'
            section.labelPositioning: ViewSection.InlineLabels | ViewSection.CurrentLabelAtStart
            section.delegate: QQC2.Button {
                required property string section
                text: section
            }
            delegate: QQC2.Label {
                text: model.t
            }
        }
    }
}
Zren commented 3 years ago

2020-11-15___11-10-42

Android Google Calendar has an option to toggle "Week 36, " but will always show the following in the agenda view:

So 5 different translation messages. It's difficult to translate though as we have 2 dates in a single format. Dec 20 - 26 needs to be

It's probably easy to do:

matty-r commented 3 years ago

I got something similar going at the moment - just need to figure out the best way to center the line going across.

weeknumber

matty-r commented 3 years ago

Ok, I've got it showing a label at the top of the scrollview, as well as inline with the other weeks. I added model.week to the AgendaModel, and just need a good way of calculating the week number when it adds the agenda item.

If I could read the week number from the Calendar, that would be ideal as it would ensure it matches up with what the user is seeing when they enable the Week View on the calendar.

Zren commented 3 years ago

Unfortunately it's not that easy.

So we'll need to implement the weekNumber function.

int QDate::weekNumber(int *yearNumber) const
{
    if (!isValid())
        return 0;

    // This could be replaced by use of QIso8601Calendar, once we implement it.
    // The Thursday of the same week determines our answer:
    QDate thursday(addDays(4 - dayOfWeek()));
    int year = thursday.year();
    // Week n's Thurs's DOY has 1 <= DOY - 7*(n-1) < 8, so 0 <= DOY + 6 - 7*n < 7:
    int week = (thursday.dayOfYear() + 6) / 7;

    if (yearNumber)
        *yearNumber = year;
    return week;
}
int QDate::dayOfYear() const
{
    if (isValid()) {
        qint64 first;
        if (QGregorianCalendar::julianFromParts(year(), 1, 1, &first))
            return jd - first + 1;
    }
    return 0;
}
bool QGregorianCalendar::julianFromParts(int year, int month, int day, qint64 *jd)
{
    Q_ASSERT(jd);
    if (!validParts(year, month, day))
        return false;

    if (year < 0)
        ++year;

    /*
     * Math from The Calendar FAQ at http://www.tondering.dk/claus/cal/julperiod.php
     * This formula is correct for all julian days, when using mathematical integer
     * division (round to negative infinity), not c++11 integer division (round to zero)
     */
    int    a = month < 3 ? 1 : 0;
    qint64 y = qint64(year) + 4800 - a;
    int    m = month + 12 * a - 3;
    *jd = day + qDiv(153 * m + 2, 5) - 32045
        + 365 * y + qDiv(y, 4) - qDiv(y, 100) + qDiv(y, 400);
    return true;
}
Zren commented 3 years ago

Also, a centered week separator can be done with:

section.delegate: RowLayout {
    required property string section

    width: agendaScrollView.width

    Rectangle {
        Layout.fillWidth: true
        implicitWidth: 1 * units.devicePixelRatio
        implicitHeight: 1 * units.devicePixelRatio
        color: theme.textColor
    }
    PlasmaComponents3.Label {
        text: section
    }
    Rectangle {
        Layout.fillWidth: true
        implicitWidth: 1 * units.devicePixelRatio
        implicitHeight: 1 * units.devicePixelRatio
        color: theme.textColor
    }
}
matty-r commented 3 years ago

Yea I saw that WeekNumber was a thing, believe I tried using it at some point but it was different to what the Calendar would show. I'll take a closer look at it.

I hadnt quiet figured out how to have centred text, so thanks for that. :)

Zren commented 3 years ago

Minor bug in the logic as I'm getting week 53, but it kinda works: https://github.com/Zren/plasma-applet-eventcalendar/compare/scrollview2

2020-11-17___18-36-31

Or maybe not as that's what google and DigitalClock shows: 2020-11-17___18-40-58

matty-r commented 3 years ago

I've been having a think about this - and we should probably use some C++ and use QDate https://doc.qt.io/qt-5/qdate.html rather than trying to write our own logic.

Zren commented 3 years ago

You can't add any C++ qml plugins otherwise it can't be downloaded from the KDE Store.

matty-r commented 3 years ago

Really? Wouldn't it just be importing a library like any other? There is python there - maybe there would be a better suited way to do it through python instead.

Zren commented 3 years ago

In order to calculate it through python, we'd need to execute 31 + 14 python processes unless we batched the entire thing at in one call. In any case, it's far less efficient and way more complicated that porting the logic ourselves.

The getDayOfWeek() in the new DateFuncs.js works to get the week number. Looks like I named the function incorrectly. I was put off by there being 53 weeks in a year, but it makes sense once you remember every year doesn't start on Jan 1st.

Edit: For reference, here's the Python weeknumber calculation:

matty-r commented 3 years ago

Ah ok. In any case, ill leave this one alone then and let you do it. I'll look at something else to fix :)