You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdepim/kalarm/repetition.cpp

365 lines
12 KiB

/*
* repetition.cpp - pushbutton and dialogue to specify alarm sub-repetition
* Program: kalarm
* Copyright © 2004,2005,2007,2008 by David Jarvie <djarvie@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "kalarm.h"
#include <qlayout.h>
#include <qwhatsthis.h>
#include <kdebug.h>
#include <kdialog.h>
#include <klocale.h>
#include "buttongroup.h"
#include "radiobutton.h"
#include "spinbox.h"
#include "timeperiod.h"
#include "timeselector.h"
#include "repetition.moc"
/*=============================================================================
= Class RepetitionButton
= Button to display the Alarm Sub-Repetition dialogue.
=============================================================================*/
RepetitionButton::RepetitionButton(const QString& caption, bool waitForInitialisation, QWidget* parent, const char* name)
: QPushButton(caption, parent, name),
mDialog(0),
mInterval(0),
mCount(0),
mMaxDuration(-1),
mDateOnly(false),
mWaitForInit(waitForInitialisation),
mReadOnly(false)
{
setToggleButton(true);
setOn(false);
connect(this, SIGNAL(clicked()), SLOT(slotPressed()));
}
void RepetitionButton::set(int interval, int count)
{
mInterval = interval;
mCount = count;
setOn(mInterval && mCount);
}
/******************************************************************************
* Set the data for the dialog.
*/
void RepetitionButton::set(int interval, int count, bool dateOnly, int maxDuration)
{
mInterval = interval;
mCount = count;
mMaxDuration = maxDuration;
mDateOnly = dateOnly;
setOn(mInterval && mCount);
}
/******************************************************************************
* Create the alarm repetition dialog.
* If 'waitForInitialisation' is true, the dialog won't be displayed until set()
* is called to initialise its data.
*/
void RepetitionButton::activate(bool waitForInitialisation)
{
if (!mDialog)
mDialog = new RepetitionDlg(i18n("Alarm Sub-Repetition"), mReadOnly, this);
mDialog->set(mInterval, mCount, mDateOnly, mMaxDuration);
if (waitForInitialisation)
emit needsInitialisation(); // request dialog initialisation
else
displayDialog(); // display the dialog now
}
/******************************************************************************
* Set the data for the dialog and display it.
* To be called only after needsInitialisation() has been emitted.
*/
void RepetitionButton::initialise(int interval, int count, bool dateOnly, int maxDuration)
{
if (maxDuration > 0 && interval > maxDuration)
count = 0;
mCount = count;
mInterval = interval;
mMaxDuration = maxDuration;
mDateOnly = dateOnly;
if (mDialog)
{
mDialog->set(interval, count, dateOnly, maxDuration);
displayDialog(); // display the dialog now
}
else
setOn(mInterval && mCount);
}
/******************************************************************************
* Display the alarm sub-repetition dialog.
* Alarm repetition has the following restrictions:
* 1) Not allowed for a repeat-at-login alarm
* 2) For a date-only alarm, the repeat interval must be a whole number of days.
* 3) The overall repeat duration must be less than the recurrence interval.
*/
void RepetitionButton::displayDialog()
{
kdDebug(5950) << "RepetitionButton::displayDialog()" << endl;
bool change = false;
if (mReadOnly)
{
mDialog->setReadOnly(true);
mDialog->exec();
}
else if (mDialog->exec() == QDialog::Accepted)
{
mCount = mDialog->count();
mInterval = mDialog->interval();
change = true;
}
setOn(mInterval && mCount);
delete mDialog;
mDialog = 0;
if (change)
emit changed(); // delete dialog first, or initialise() will redisplay dialog
}
/*=============================================================================
= Class RepetitionDlg
= Alarm sub-repetition dialogue.
=============================================================================*/
static const int MAX_COUNT = 9999; // maximum range for count spinbox
RepetitionDlg::RepetitionDlg(const QString& caption, bool readOnly, QWidget* parent, const char* name)
: KDialogBase(parent, name, true, caption, Ok|Cancel),
mMaxDuration(-1),
mDateOnly(false),
mReadOnly(readOnly)
{
int spacing = spacingHint();
QWidget* page = new QWidget(this);
setMainWidget(page);
QVBoxLayout* topLayout = new QVBoxLayout(page, 0, spacing);
mTimeSelector = new TimeSelector(i18n("Repeat every 10 minutes", "&Repeat every"), QString::null,
i18n("Instead of the alarm triggering just once at each recurrence, "
"checking this option makes the alarm trigger multiple times at each recurrence."),
i18n("Enter the time between repetitions of the alarm"),
true, page);
mTimeSelector->setFixedSize(mTimeSelector->sizeHint());
connect(mTimeSelector, SIGNAL(valueChanged(int)), SLOT(intervalChanged(int)));
connect(mTimeSelector, SIGNAL(toggled(bool)), SLOT(repetitionToggled(bool)));
topLayout->addWidget(mTimeSelector, 0, Qt::AlignAuto);
mButtonGroup = new ButtonGroup(page, "buttonGroup");
connect(mButtonGroup, SIGNAL(buttonSet(int)), SLOT(typeClicked()));
topLayout->addWidget(mButtonGroup);
QBoxLayout* vlayout = new QVBoxLayout(mButtonGroup, marginHint(), spacing);
QBoxLayout* layout = new QHBoxLayout(vlayout, spacing);
mCountButton = new RadioButton(i18n("&Number of repetitions:"), mButtonGroup);
mCountButton->setFixedSize(mCountButton->sizeHint());
QWhatsThis::add(mCountButton,
i18n("Check to specify the number of times the alarm should repeat after each recurrence"));
layout->addWidget(mCountButton);
mCount = new SpinBox(1, MAX_COUNT, 1, mButtonGroup);
mCount->setFixedSize(mCount->sizeHint());
mCount->setLineShiftStep(10);
mCount->setSelectOnStep(false);
connect(mCount, SIGNAL(valueChanged(int)), SLOT(countChanged(int)));
QWhatsThis::add(mCount,
i18n("Enter the number of times to trigger the alarm after its initial occurrence"));
layout->addWidget(mCount);
mCountButton->setFocusWidget(mCount);
layout->addStretch();
layout = new QHBoxLayout(vlayout, spacing);
mDurationButton = new RadioButton(i18n("&Duration:"), mButtonGroup);
mDurationButton->setFixedSize(mDurationButton->sizeHint());
QWhatsThis::add(mDurationButton,
i18n("Check to specify how long the alarm is to be repeated"));
layout->addWidget(mDurationButton);
mDuration = new TimePeriod(true, mButtonGroup);
mDuration->setFixedSize(mDuration->sizeHint());
connect(mDuration, SIGNAL(valueChanged(int)), SLOT(durationChanged(int)));
QWhatsThis::add(mDuration,
i18n("Enter the length of time to repeat the alarm"));
layout->addWidget(mDuration);
mDurationButton->setFocusWidget(mDuration);
layout->addStretch();
mCountButton->setChecked(true);
repetitionToggled(false);
setReadOnly(mReadOnly);
}
/******************************************************************************
* Set the state of all controls to reflect the data in the specified alarm.
*/
void RepetitionDlg::set(int interval, int count, bool dateOnly, int maxDuration)
{
if (!interval)
count = 0;
else if (!count)
interval = 0;
if (dateOnly != mDateOnly)
{
mDateOnly = dateOnly;
mTimeSelector->setDateOnly(mDateOnly);
mDuration->setDateOnly(mDateOnly);
}
mMaxDuration = maxDuration;
if (mMaxDuration)
{
int maxhm = (mMaxDuration > 0) ? mMaxDuration : 9999;
int maxdw = (mMaxDuration > 0) ? mMaxDuration / 1440 : 9999;
mTimeSelector->setMaximum(maxhm, maxdw);
mDuration->setMaximum(maxhm, maxdw);
}
// Set the units - needed later if the control is unchecked initially.
TimePeriod::Units units = mDateOnly ? TimePeriod::DAYS : TimePeriod::HOURS_MINUTES;
mTimeSelector->setMinutes(interval, mDateOnly, units);
if (!mMaxDuration || !count)
mTimeSelector->setChecked(false);
else
{
bool on = mTimeSelector->isChecked();
repetitionToggled(on); // enable/disable controls
if (on)
intervalChanged(interval); // ensure mCount range is set
mCount->setValue(count);
mDuration->setMinutes(count * interval, mDateOnly, units);
mCountButton->setChecked(true);
}
mTimeSelector->setEnabled(mMaxDuration);
}
/******************************************************************************
* Set the read-only status.
*/
void RepetitionDlg::setReadOnly(bool ro)
{
ro = ro || mReadOnly;
mTimeSelector->setReadOnly(ro);
mCountButton->setReadOnly(ro);
mCount->setReadOnly(ro);
mDurationButton->setReadOnly(ro);
mDuration->setReadOnly(ro);
}
/******************************************************************************
* Get the period between repetitions in minutes.
*/
int RepetitionDlg::interval() const
{
return mTimeSelector->minutes();
}
/******************************************************************************
* Set the entered repeat count.
*/
int RepetitionDlg::count() const
{
int interval = mTimeSelector->minutes();
if (interval)
{
if (mCountButton->isOn())
return mCount->value();
if (mDurationButton->isOn())
return mDuration->minutes() / interval;
}
return 0; // no repetition
}
/******************************************************************************
* Called when the time interval widget has changed value.
* Adjust the maximum repetition count accordingly.
*/
void RepetitionDlg::intervalChanged(int minutes)
{
if (mTimeSelector->isChecked() && minutes > 0)
{
mCount->setRange(1, (mMaxDuration >= 0 ? mMaxDuration / minutes : MAX_COUNT));
if (mCountButton->isOn())
countChanged(mCount->value());
else
durationChanged(mDuration->minutes());
}
}
/******************************************************************************
* Called when the count spinbox has changed value.
* Adjust the duration accordingly.
*/
void RepetitionDlg::countChanged(int count)
{
int interval = mTimeSelector->minutes();
if (interval)
{
bool blocked = mDuration->signalsBlocked();
mDuration->blockSignals(true);
mDuration->setMinutes(count * interval, mDateOnly,
(mDateOnly ? TimePeriod::DAYS : TimePeriod::HOURS_MINUTES));
mDuration->blockSignals(blocked);
}
}
/******************************************************************************
* Called when the duration widget has changed value.
* Adjust the count accordingly.
*/
void RepetitionDlg::durationChanged(int minutes)
{
int interval = mTimeSelector->minutes();
if (interval)
{
bool blocked = mCount->signalsBlocked();
mCount->blockSignals(true);
mCount->setValue(minutes / interval);
mCount->blockSignals(blocked);
}
}
/******************************************************************************
* Called when the time period widget is toggled on or off.
*/
void RepetitionDlg::repetitionToggled(bool on)
{
if (mMaxDuration == 0)
on = false;
mButtonGroup->setEnabled(on);
mCount->setEnabled(on && mCountButton->isOn());
mDuration->setEnabled(on && mDurationButton->isOn());
}
/******************************************************************************
* Called when one of the count or duration radio buttons is toggled.
*/
void RepetitionDlg::typeClicked()
{
if (mTimeSelector->isChecked())
{
mCount->setEnabled(mCountButton->isOn());
mDuration->setEnabled(mDurationButton->isOn());
}
}