Commit 5b4e7638 authored by David Jarvie's avatar David Jarvie
Browse files

Add date selector option to enable alarm list view to be filtered

parent 2a57c2fb
Pipeline #69523 passed with stage
in 6 minutes and 1 second
......@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.16 FATAL_ERROR)
set(PIM_VERSION "5.17.80")
set(PIM_VERSION ${PIM_VERSION})
set(RELEASE_SERVICE_VERSION "21.08.0")
set(KALARM_VERSION "3.2.2")
set(KALARM_VERSION "3.3.0")
project(kalarm VERSION ${KALARM_VERSION})
......
KAlarm Change Log
=== Version 3.3.0 (KDE Applications 21.08) --- 9 July 2021 ===
* Add date selector option to filter alarms.
=== Version 3.2.2 (KDE Applications 21.04.2) --- 26 May 2021 ===
* In audio alarm edit dialogue, don't show file name in encoded format [KDE Bug 437676]
......
......@@ -31,7 +31,7 @@
</authorgroup>
<copyright>
<year>2001</year><year>2002</year><year>2003</year><year>2004</year><year>2005</year><year>2006</year><year>2007</year><year>2008</year><year>2009</year><year>2010</year><year>2011</year><year>2012</year><year>2013</year><year>2016</year><year>2018</year><year>2019</year><year>2020</year>
<year>2001</year><year>2002</year><year>2003</year><year>2004</year><year>2005</year><year>2006</year><year>2007</year><year>2008</year><year>2009</year><year>2010</year><year>2011</year><year>2012</year><year>2013</year><year>2016</year><year>2018</year><year>2019</year><year>2020</year><year>2021</year>
<holder>&David.Jarvie;</holder>
</copyright>
......@@ -39,8 +39,8 @@
<!-- Don't change format of date and version of the documentation -->
<date>2020-10-28</date>
<releaseinfo>3.1.0 (Applications 20.12)</releaseinfo>
<date>2021-7-9</date>
<releaseinfo>3.3.0 (Applications 21.08)</releaseinfo>
<abstract>
<para>&kalarm; is a personal alarm message, command and email scheduler by &kde;.</para>
......@@ -267,6 +267,21 @@ Alarms</guimenuitem></menuchoice>.</para>
</sect2>
<sect2 id="datepicker">
<title>Filtering the Alarm List by Date</title>
<para>You can restrict the alarm list to show only alarms which are
scheduled to occur on a selected date. This is achieved by means of
the alarm date selector, which can be displayed or hidden by
<menuchoice><guimenu>View</guimenu>
<guimenuitem>Show Date Selector</guimenuitem>
</menuchoice>. Select a date by clicking on it in the date selector,
or deselect it by clicking on it again. The date selector displays a
single month. To display a different month, use the arrow controls in
the date selector.</para>
</sect2>
<sect2 id="search">
<title>Searching the Alarm List</title>
......@@ -347,6 +362,15 @@ the context menu.</para>
various sources:</para>
<itemizedlist>
<listitem>
<para>To preset the alarm's date in the
<link linkend="alarm-edit-dlg">Alarm Edit dialog</link>,
<mousebutton>right</mousebutton> click on the desired date in the alarm
date selector (see <link linkend="datepicker">Filtering the Alarm List
by Date</link>) and select the appropriate alarm type from the context
menu.</para>
</listitem>
<listitem>
<para>To base your new alarm on an alarm template, follow the
instructions in the <link linkend="templates">Alarm Templates</link>
......
......@@ -121,6 +121,8 @@ set(kalarm_bin_SRCS ${libkalarm_SRCS} ${resources_SRCS}
newalarmaction.cpp
commandoptions.cpp
resourceselector.cpp
datepicker.cpp
daymatrix.cpp
templatepickdlg.cpp
templatedlg.cpp
templatemenuaction.cpp
......
<!DOCTYPE gui>
<gui name="kalarm" version="310" >
<gui name="kalarm" version="330" >
<ToolBar noMerge="1" name="mainToolBar" >
<Action name="new" />
<Separator/>
......@@ -46,7 +46,9 @@
<text>&amp;View</text>
<Action name="showArchivedAlarms" />
<Action name="showInSystemTray" />
<Separator/>
<Action name="showResources" />
<Action name="showDateNavigator" />
<Separator/>
<Action name="spread" />
</Menu>
......
/*
* datepicker.cpp - date chooser widget
* Program: kalarm
* SPDX-FileCopyrightText: 2021 David Jarvie <djarvie@kde.org>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "datepicker.h"
#include "daymatrix.h"
#include "functions.h"
#include "preferences.h"
#include "lib/locale.h"
#include "lib/synchtimer.h"
#include <KAlarmCal/KADateTime>
#include <KLocalizedString>
#include <QLabel>
#include <QToolButton>
#include <QGridLayout>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QLocale>
#include <QApplication>
DatePicker::DatePicker(QWidget* parent)
: QWidget(parent)
{
const QString whatsThis = i18nc("@info:whatsthis", "Select dates to show in the alarm list. Only alarms due on these dates will be shown.");
QVBoxLayout* topLayout = new QVBoxLayout(this);
const int spacing = topLayout->spacing();
topLayout->setSpacing(0);
QLabel* label = new QLabel(i18nc("@title:group", "Alarm Date Selector"), this);
label->setAlignment(Qt::AlignCenter);
label->setWordWrap(true);
label->setWhatsThis(whatsThis);
topLayout->addWidget(label, 0, Qt::AlignHCenter);
topLayout->addSpacing(spacing);
// Set up the month/year navigation buttons at the top.
QHBoxLayout* hlayout = new QHBoxLayout;
hlayout->setContentsMargins(0, 0, 0, 0);
topLayout->addLayout(hlayout);
QToolButton* leftYear = createArrowButton(QStringLiteral("arrow-left-double"));
QToolButton* leftMonth = createArrowButton(QStringLiteral("arrow-left"));
QToolButton* rightMonth = createArrowButton(QStringLiteral("arrow-right"));
QToolButton* rightYear = createArrowButton(QStringLiteral("arrow-right-double"));
mPrevYear = leftYear;
mPrevMonth = leftMonth;
mNextYear = rightYear;
mNextMonth = rightMonth;
if (QApplication::isRightToLeft())
{
mPrevYear = rightYear;
mPrevMonth = rightMonth;
mNextYear = leftYear;
mNextMonth = leftMonth;
}
mPrevYear->setToolTip(i18nc("@info:tooltip", "Show the previous year"));
mPrevMonth->setToolTip(i18nc("@info:tooltip", "Show the previous month"));
mNextYear->setToolTip(i18nc("@info:tooltip", "Show the next year"));
mNextMonth->setToolTip(i18nc("@info:tooltip", "Show the next month"));
connect(mPrevYear, &QToolButton::clicked, this, &DatePicker::prevYearClicked);
connect(mPrevMonth, &QToolButton::clicked, this, &DatePicker::prevMonthClicked);
connect(mNextYear, &QToolButton::clicked, this, &DatePicker::nextYearClicked);
connect(mNextMonth, &QToolButton::clicked, this, &DatePicker::nextMonthClicked);
const QDate currentDate = KADateTime::currentDateTime(Preferences::timeSpec()).date();
mMonthYear = new QLabel(this);
mMonthYear->setAlignment(Qt::AlignCenter);
QLocale locale;
QDate d(currentDate.year(), 1, 1);
int maxWidth = 0;
for (int i = 1; i <= 12; ++i)
{
mMonthYear->setText(locale.toString(d, QStringLiteral("MMM yyyy")));
maxWidth = std::max(maxWidth, mMonthYear->minimumSizeHint().width());
d = d.addMonths(1);
}
mMonthYear->setMinimumWidth(maxWidth);
hlayout->addWidget(mPrevYear);
hlayout->addWidget(mPrevMonth);
hlayout->addStretch();
hlayout->addWidget(mMonthYear);
hlayout->addStretch();
hlayout->addWidget(mNextMonth);
hlayout->addWidget(mNextYear);
// Set up the day name headings.
// These start at the user's start day of the week.
QWidget* widget = new QWidget(this); // this is to control the QWhatsThis text display area
widget->setWhatsThis(whatsThis);
topLayout->addWidget(widget);
QVBoxLayout* vlayout = new QVBoxLayout(widget);
vlayout->setContentsMargins(0, 0, 0, 0);
QGridLayout* grid = new QGridLayout;
grid->setSpacing(0);
grid->setContentsMargins(0, 0, 0, 0);
vlayout->addLayout(grid);
mDayNames = new QLabel[7];
maxWidth = 0;
for (int i = 0; i < 7; ++i)
{
const int day = Locale::localeDayInWeek_to_weekDay(i);
mDayNames[i].setText(locale.dayName(day, QLocale::ShortFormat));
mDayNames[i].setAlignment(Qt::AlignCenter);
maxWidth = std::max(maxWidth, mDayNames[i].minimumSizeHint().width());
grid->addWidget(&mDayNames[i], 0, i, 1, 1, Qt::AlignCenter);
}
for (int i = 0; i < 7; ++i)
mDayNames[i].setMinimumWidth(maxWidth);
mDayMatrix = new DayMatrix(widget);
mDayMatrix->setWhatsThis(whatsThis);
vlayout->addWidget(mDayMatrix);
connect(mDayMatrix, &DayMatrix::selected, this, &DatePicker::datesSelected);
connect(mDayMatrix, &DayMatrix::newAlarm, this, &DatePicker::slotNewAlarm);
connect(mDayMatrix, &DayMatrix::newAlarmFromTemplate, this, &DatePicker::slotNewAlarmFromTemplate);
// Initialise the display.
mMonthShown.setDate(currentDate.year(), currentDate.month(), 1);
newMonthShown();
updateDisplay();
MidnightTimer::connect(this, SLOT(updateToday()));
}
DatePicker::~DatePicker()
{
delete[] mDayNames;
}
QVector<QDate> DatePicker::selectedDates() const
{
return mDayMatrix->selectedDates();
}
void DatePicker::clearSelection()
{
mDayMatrix->clearSelection();
}
/******************************************************************************
* Called when the widget is shown. Set the row height for the day matrix.
*/
void DatePicker::showEvent(QShowEvent* e)
{
mDayMatrix->setRowHeight(mDayNames[0].height());
QWidget::showEvent(e);
}
/******************************************************************************
* Called when the previous year arrow button has been clicked.
*/
void DatePicker::prevYearClicked()
{
newMonthShown();
if (mPrevYear->isEnabled())
{
mMonthShown = mMonthShown.addYears(-1);
newMonthShown();
updateDisplay();
}
}
/******************************************************************************
* Called when the previous month arrow button has been clicked.
*/
void DatePicker::prevMonthClicked()
{
newMonthShown();
if (mPrevMonth->isEnabled())
{
mMonthShown = mMonthShown.addMonths(-1);
newMonthShown();
updateDisplay();
}
}
/******************************************************************************
* Called when the next year arrow button has been clicked.
*/
void DatePicker::nextYearClicked()
{
mMonthShown = mMonthShown.addYears(1);
newMonthShown();
updateDisplay();
}
/******************************************************************************
* Called when the next month arrow button has been clicked.
*/
void DatePicker::nextMonthClicked()
{
mMonthShown = mMonthShown.addMonths(1);
newMonthShown();
updateDisplay();
}
/******************************************************************************
* Called at midnight. If the month has changed, update the view.
*/
void DatePicker::updateToday()
{
const QDate currentDate = KADateTime::currentDateTime(Preferences::timeSpec()).date();
const QDate monthToShow(currentDate.year(), currentDate.month(), 1);
if (monthToShow > mMonthShown)
{
mMonthShown = monthToShow;
newMonthShown();
updateDisplay();
}
else
mDayMatrix->updateToday(currentDate);
}
/******************************************************************************
* Called when a new month is shown, to enable/disable 'previous' arrow buttons.
*/
void DatePicker::newMonthShown()
{
QLocale locale;
mMonthYear->setText(locale.toString(mMonthShown, QStringLiteral("MMM yyyy")));
const QDate currentDate = KADateTime::currentDateTime(Preferences::timeSpec()).date();
mPrevMonth->setEnabled(mMonthShown > currentDate);
mPrevYear->setEnabled(mMonthShown.addMonths(-11) > currentDate);
}
/******************************************************************************
* Called when the "New Alarm" menu item is selected to edit a new alarm.
*/
void DatePicker::slotNewAlarm(EditAlarmDlg::Type type)
{
const QVector<QDate> selectedDates = mDayMatrix->selectedDates();
const QDate startDate = selectedDates.isEmpty() ? QDate() : selectedDates[0];
KAlarm::editNewAlarm(type, startDate);
}
/******************************************************************************
* Called when the "New Alarm" menu item is selected to edit a new alarm from a
* template.
*/
void DatePicker::slotNewAlarmFromTemplate(const KAEvent& event)
{
const QVector<QDate> selectedDates = mDayMatrix->selectedDates();
const QDate startDate = selectedDates.isEmpty() ? QDate() : selectedDates[0];
KAlarm::editNewAlarm(event, startDate);
}
/******************************************************************************
* Update the days shown.
*/
void DatePicker::updateDisplay()
{
const int firstDay = Locale::weekDay_to_localeDayInWeek(mMonthShown.dayOfWeek());
mStartDate = mMonthShown.addDays(-firstDay);
mDayMatrix->setStartDate(mStartDate);
mDayMatrix->update();
mDayMatrix->repaint();
}
/******************************************************************************
* Create an arrow button for moving backwards or forwards.
*/
QToolButton* DatePicker::createArrowButton(const QString& iconId)
{
QToolButton* button = new QToolButton(this);
button->setIcon(QIcon::fromTheme(iconId));
button->setToolButtonStyle(Qt::ToolButtonIconOnly);
button->setAutoRaise(true);
return button;
}
// vim: et sw=4:
/*
* datepicker.h - date chooser widget
* Program: kalarm
* SPDX-FileCopyrightText: 2021 David Jarvie <djarvie@kde.org>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef DATEPICKER_H
#define DATEPICKER_H
#include "editdlg.h"
#include <QWidget>
#include <QDate>
class QToolButton;
class QLabel;
class DayMatrix;
/**
* Displays the calendar for a month, to allow the user to select days.
* Dates before today are disabled.
*/
class DatePicker : public QWidget
{
Q_OBJECT
public:
explicit DatePicker(QWidget* parent = nullptr);
~DatePicker() override;
/** Return the currently selected dates, if any. */
QVector<QDate> selectedDates() const;
/** Deselect all dates. */
void clearSelection();
Q_SIGNALS:
/** Emitted when the user selects or deselects dates.
*
* @param dates The dates selected, in date order, or empty if none.
*/
void datesSelected(const QVector<QDate>& dates);
protected:
void showEvent(QShowEvent*) override;
private Q_SLOTS:
void prevYearClicked();
void prevMonthClicked();
void nextYearClicked();
void nextMonthClicked();
void updateToday();
void slotNewAlarm(EditAlarmDlg::Type);
void slotNewAlarmFromTemplate(const KAEvent&);
private:
void newMonthShown();
void updateDisplay();
QToolButton* createArrowButton(const QString& iconId);
QToolButton* mPrevYear;
QToolButton* mPrevMonth;
QToolButton* mNextYear;
QToolButton* mNextMonth;
QLabel* mMonthYear;
QLabel* mDayNames;
DayMatrix* mDayMatrix;
QDate mMonthShown; // 1st of month currently displayed
QDate mStartDate; // earliest date currently displayed
};
#endif // DATEPICKER_H
// vim: et sw=4:
This diff is collapsed.
/*
* daymatrix.h - calendar day matrix display
* Program: kalarm
* This class is adapted from KODayMatrix in KOrganizer.
*
* SPDX-FileCopyrightText: 2001 Eitzenberger Thomas <thomas.eitzenberger@siemens.at>
* SPDX-FileCopyrightText: 2003 Cornelius Schumacher <schumacher@kde.org>
* SPDX-FileCopyrightText: 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
* SPDX-FileCopyrightText: 2021 David Jarvie <djarvie@kde.org>
*
* SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0
*/
#ifndef DAYMATRIX_H
#define DAYMATRIX_H
#include "editdlg.h"
#include <KAlarmCal/KAEvent>
#include <QFrame>
#include <QDate>
#include <QSet>
class Resource;
namespace { class TextColours; }
/**
* Displays one month's dates in a grid, one line per week, highlighting days
* on which alarms occur. It has an option to allow one or more consecutive
* days to be selected by dragging the mouse. Days before today are disabled.
*/
class DayMatrix : public QFrame
{
Q_OBJECT
public:
/** constructor to create a day matrix widget.
*
* @param parent widget that is the parent of the day matrix.
* Normally this should be a KDateNavigator
*/
explicit DayMatrix(QWidget* parent = nullptr);
/** destructor that deallocates all dynamically allocated private members.
*/
~DayMatrix() override;
/** Set a new start date for the matrix. If changed, or other changes are
* pending, recalculates which days in the matrix alarms occur on, and
* which are holidays/non-work days, and repaints.
*
* @param startDate The first day to be displayed in the matrix.
*/
void setStartDate(const QDate& startDate);
/** Notify the matrix that the current date has changed.
* The month currently being displayed will not be changed.
*/
void updateToday(const QDate& newDate);
/** Returns all selected dates, in date order. */
QVector<QDate> selectedDates() const;
/** Clear all selections. */
void clearSelection();
void setRowHeight(int rowHeight);
Q_SIGNALS:
/** Emitted when the user selects or deselects dates.
*
* @param dates The dates selected, in date order, or empty if none.
*/
void selected(const QVector<QDate>& dates);
void newAlarm(EditAlarmDlg::Type);
void newAlarmFromTemplate(const KAEvent&);
protected:
bool event(QEvent*) override;
void paintEvent(QPaintEvent*) override;
void mousePressEvent(QMouseEvent*) override;
void mouseReleaseEvent(QMouseEvent*) override;
void mouseMoveEvent(QMouseEvent*) override;
void resizeEvent(QResizeEvent*) override;
private Q_SLOTS:
void resourceUpdated(Resource&);
void resourceRemoved(KAlarmCal::ResourceId);
void slotUpdateView();
private:
bool recalculateToday();
QString getHolidayLabel(int offset) const;
void setMouseSelection(int start, int end, bool emitSignal);
void popupMenu(); // pop up a context menu for creating a new alarm
int getDayIndex(const QPoint&) const; // get index of the day located at a point in the matrix
// If changes are pending, recalculates which days in the matrix have
// alarms occurring, and which are holidays/non-work days, and repaints.
void updateView();
void updateEvents();
void colourBackground(QPainter&, const QColor&, int start, int end);
QColor textColour(const TextColours&, const QPalette&, int dayIndex, bool workDay) const;
int mRowHeight {1}; // height of each row
QDate mStartDate; // starting date of the matrix
QVector<QString> mDayLabels; // array of day labels, to optimize drawing performance
QSet<QDate> mEventDates; // days on which alarms occur
QStringList mHolidays; // holiday names, indexed by day index
int mTodayIndex {-1}; // index of today, or -1 if today is not visible in the matrix
int mMonthStartIndex; // index of the first day of the main month shown
int mMonthEndIndex; // index of the last day of the main month shown
int mSelInit; // index of day where dragged selection was initiated
int mSelStart; // index of the first selected day
int mSelEnd; // index of the last selected day
QVector<QDate> mLastSelectedDates; // last dates emitted in selected() signal
QRectF mDaySize; // the geometric size of each day in the matrix
bool mAllowMultipleSelection {false}; // selection may contain multiple days
bool mSelectionMustBeVisible {true}; // selection will be cancelled if not wholly visible
bool mPendingChanges {false}; // the display needs to be updated
};
#endif // DAYMATRIX_H
// vim: et sw=4:
......@@ -11,6 +11,7 @@
#include "alarmlistdelegate.h"
#include "alarmlistview.h"
#include "birthdaydlg.h"
#include "datepicker.h"
#include "functions.h"
#include "kalarmapp.h"
#include "kamail.h"
......@@ -58,6 +59,7 @@ using namespace KCalUtils;
#include <QAction>
#include <QSplitter>
#include <QVBoxLayout>
#include <QDragEnterEvent>
#include <QDropEvent>
#include <QResizeEvent>
......@@ -81,10 +83,12 @@ namespace
const QString UI_FILE(QStringLiteral("kalarmui.rc"));
const char* WINDOW_NAME = "MainWindow";
const char* VIEW_GROUP = "View";
const char* SHOW_COLUMNS = "ShowColumns";
const char* SHOW_ARCHIVED_KEY = "ShowArchivedAlarms";
const char* SHOW_RESOURCES_KEY = "ShowResources";
const char* VIEW_GROUP = "View";
const char* SHOW_COLUMNS = "ShowColumns";