<commit_before>/*
 *  timeperiod.h  -  time period data entry widget
 *  Program:  kalarm
 *  (C) 2003, 2004 by David Jarvie <software@astrojar.org.uk>
 *
 *  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

#include "kalarm.h"

#include <qwidgetstack.h>
#include <qwhatsthis.h>

#include <klocale.h>
#include <kdialog.h>

#include "combobox.h"
#include "spinbox.h"
#include "timespinbox.h"
#include "timeperiod.moc"

// Collect these widget labels together to ensure consistent wording and
// translations across different modules.
QString TimePeriod::i18n_hours_mins()   { return i18n("hours/minutes"); }
QString TimePeriod::i18n_Hours_Mins()   { return i18n("Hours/Minutes"); }
QString TimePeriod::i18n_days()         { return i18n("days"); }
QString TimePeriod::i18n_Days()         { return i18n("Days"); }
QString TimePeriod::i18n_weeks()        { return i18n("weeks"); }
QString TimePeriod::i18n_Weeks()        { return i18n("Weeks"); }

static const int maxMinutes = 100*60-1;   // absolute maximum value for hours:minutes = 99H59M

/*=============================================================================
= Class TimePeriod
= Contains a time unit combo box, plus a time spinbox, to select a time period.
=============================================================================*/

TimePeriod::TimePeriod(bool allowHourMinute, QWidget* parent, const char* name)
	: QHBox(parent, name),
	  mMaxDays(9999),
	  mNoHourMinute(!allowHourMinute),
	  mReadOnly(false)
{
	setSpacing(KDialog::spacingHint());

	mSpinStack = new QWidgetStack(this);
	mSpinBox = new SpinBox(mSpinStack);
	mSpinBox->setLineStep(1);
	mSpinBox->setLineShiftStep(10);
	mSpinBox->setRange(1, mMaxDays);
	connect(mSpinBox, SIGNAL(valueChanged(int)), SLOT(slotDaysChanged(int)));
	mSpinStack->addWidget(mSpinBox, 0);

	mTimeSpinBox = new TimeSpinBox(0, 99999, mSpinStack);
	mTimeSpinBox->setRange(1, maxMinutes);    // max 99H59M
	connect(mTimeSpinBox, SIGNAL(valueChanged(int)), SLOT(slotTimeChanged(int)));
	mSpinStack->addWidget(mTimeSpinBox, 1);

	mSpinStack->setFixedSize(mSpinBox->sizeHint().expandedTo(mTimeSpinBox->sizeHint()));
	mHourMinuteRaised = mNoHourMinute;
	showHourMin(!mNoHourMinute);

	mUnitsCombo = new ComboBox(false, this);
	if (mNoHourMinute)
		mDateOnlyOffset = 1;
	else
	{
		mDateOnlyOffset = 0;
		mUnitsCombo->insertItem(i18n_hours_mins());
	}
	mUnitsCombo->insertItem(i18n_days());
	mUnitsCombo->insertItem(i18n_weeks());
	mMaxUnitShown = WEEKS;
	mUnitsCombo->setFixedSize(mUnitsCombo->sizeHint());
	connect(mUnitsCombo, SIGNAL(activated(int)), SLOT(slotUnitsSelected(int)));

	setFocusProxy(mUnitsCombo);
	setTabOrder(mUnitsCombo, mSpinStack);
}

void TimePeriod::setReadOnly(bool ro)
{
	if (ro != mReadOnly)
	{
		mReadOnly = ro;
		mSpinBox->setReadOnly(ro);
		mTimeSpinBox->setReadOnly(ro);
		mUnitsCombo->setReadOnly(ro);
	}
}

/******************************************************************************
*  Set whether the editor text is to be selected whenever spin buttons are
*  clicked. Default is to select them.
*/
void TimePeriod::setSelectOnStep(bool sel)
{
	mSpinBox->setSelectOnStep(sel);
	mTimeSpinBox->setSelectOnStep(sel);
}

/******************************************************************************
*  Set the input focus on the count field.
*/
void TimePeriod::setFocusOnCount()
{
	mSpinStack->setFocus();
}

/******************************************************************************
*  Set the maximum values for the hours:minutes and days/weeks spinboxes.
*  If 'hourmin' = 0, the hours:minutes maximum is left unchanged.
*/
void TimePeriod::setMaximum(int hourmin, int days)
{
	int oldmins = minutes();
	if (hourmin > 0)
	{
		if (hourmin > maxMinutes)
			hourmin = maxMinutes;
		mTimeSpinBox->setRange(1, hourmin);
	}
	mMaxDays = (days >= 0) ? days : 0;
	adjustDayWeekShown();
	setUnitRange();
	int mins = minutes();
	if (mins != oldmins)
		emit valueChanged(mins);
}

/******************************************************************************
 * Get the specified number of minutes.
 * Reply = 0 if error.
 */
int TimePeriod::minutes() const
{
	switch (mUnitsCombo->currentItem() + mDateOnlyOffset)
	{
		case HOURS_MINUTES:
			return mTimeSpinBox->value();
		case DAYS:
			return mSpinBox->value() * 24*60;
		case WEEKS:
			return mSpinBox->value() * 7*24*60;
	}
	return 0;
}

/******************************************************************************
*  Initialise the controls with a specified time period.
*  The time unit combo-box is initialised to 'defaultUnits', but if 'dateOnly'
*  is true, it will never be initialised to hours/minutes.
*/
void TimePeriod::setMinutes(int mins, bool dateOnly, TimePeriod::Units defaultUnits)
{
	int oldmins = minutes();
	if (!dateOnly  &&  mNoHourMinute)
		dateOnly = true;
	int item;
	if (mins)
	{
		int count = mins;
		if (mins % (24*60))
			item = HOURS_MINUTES;
		else if (mins % (7*24*60))
		{
			item = DAYS;
			count = mins / (24*60);
		}
		else
		{
			item = WEEKS;
			count = mins / (7*24*60);
		}
		if (item < mDateOnlyOffset)
			item = mDateOnlyOffset;
		else if (item > mMaxUnitShown)
			item = mMaxUnitShown;
		mUnitsCombo->setCurrentItem(item - mDateOnlyOffset);
		if (item == HOURS_MINUTES)
			mTimeSpinBox->setValue(count);
		else
			mSpinBox->setValue(count);
		item = setDateOnly(mins, dateOnly, false);
	}
	else
	{
		item = defaultUnits;
		if (item < mDateOnlyOffset)
			item = mDateOnlyOffset;
		else if (item > mMaxUnitShown)
			item = mMaxUnitShown;
		mUnitsCombo->setCurrentItem(item - mDateOnlyOffset);
		if (dateOnly && !mDateOnlyOffset  ||  !dateOnly && mDateOnlyOffset)
			item = setDateOnly(mins, dateOnly, false);
	}
	showHourMin(item == HOURS_MINUTES  &&  !mNoHourMinute);

	int newmins = minutes();
	if (newmins != oldmins)
		emit valueChanged(newmins);
}

/******************************************************************************
*  Enable/disable hours/minutes units (if hours/minutes were permitted in the
*  constructor).
*/
TimePeriod::Units TimePeriod::setDateOnly(int mins, bool dateOnly, bool signal)
{
	int oldmins;
	if (signal)
		oldmins = minutes();
	int index = mUnitsCombo->currentItem();
	Units units = static_cast<Units>(index + mDateOnlyOffset);
	if (!mNoHourMinute)
	{
		if (!dateOnly  &&  mDateOnlyOffset)
		{
			// Change from date-only to allow hours/minutes
			mUnitsCombo->insertItem(i18n_hours_mins(), 0);
			mDateOnlyOffset = 0;
			adjustDayWeekShown();
			mUnitsCombo->setCurrentItem(++index);
		}
		else if (dateOnly  &&  !mDateOnlyOffset)
		{
			// Change from allowing hours/minutes to date-only
			mUnitsCombo->removeItem(0);
			mDateOnlyOffset = 1;
			if (index)
				--index;
			adjustDayWeekShown();
			mUnitsCombo->setCurrentItem(index);
			if (units == HOURS_MINUTES)
			{
				// Set units to days and round up the warning period
				units = DAYS;
				mUnitsCombo->setCurrentItem(DAYS - mDateOnlyOffset);
				mSpinBox->setValue((mins + 1439) / 1440);
			}
			showHourMin(false);
		}
	}

	if (signal)
	{
		int newmins = minutes();
		if (newmins != oldmins)
			emit valueChanged(newmins);
	}
	return units;
}

/******************************************************************************
*  Adjust the days/weeks units shown to suit the maximum days limit.
*/
void TimePeriod::adjustDayWeekShown()
{
	Units newMaxUnitShown = (mMaxDays >= 7) ? WEEKS : (mMaxDays || mDateOnlyOffset) ? DAYS : HOURS_MINUTES;
	if (newMaxUnitShown > mMaxUnitShown)
	{
		if (mMaxUnitShown < DAYS)
			mUnitsCombo->insertItem(i18n_days());
		if (newMaxUnitShown == WEEKS)
			mUnitsCombo->insertItem(i18n_weeks());
	}
	else if (newMaxUnitShown < mMaxUnitShown)
	{
		if (mMaxUnitShown == WEEKS)
			mUnitsCombo->removeItem(WEEKS - mDateOnlyOffset);
		if (newMaxUnitShown < DAYS)
			mUnitsCombo->removeItem(DAYS - mDateOnlyOffset);
	}
	mMaxUnitShown = newMaxUnitShown;
}

/******************************************************************************
*  Set the maximum value which may be entered into the day/week count field,
*  depending on the current unit selection.
*/
void TimePeriod::setUnitRange()
{
	int maxval;
	switch (static_cast<Units>(mUnitsCombo->currentItem() + mDateOnlyOffset))
	{
		case WEEKS:
			maxval = mMaxDays / 7;
			if (maxval)
				break;
			mUnitsCombo->setCurrentItem(DAYS - mDateOnlyOffset);
			// fall through to DAYS
		case DAYS:
			maxval = mMaxDays ? mMaxDays : 1;
			break;
		case HOURS_MINUTES:
		default:
			return;
	}
	mSpinBox->setRange(1, maxval);
}

/******************************************************************************
*  Called when a new item is made current in the time units combo box.
*/
void TimePeriod::slotUnitsSelected(int index)
{
	setUnitRange();
	showHourMin(index + mDateOnlyOffset == HOURS_MINUTES);
	emit valueChanged(minutes());
}

/******************************************************************************
*  Called when the value of the days/weeks spin box changes.
*/
void TimePeriod::slotDaysChanged(int)
{
	if (!mHourMinuteRaised)
		emit valueChanged(minutes());
}

/******************************************************************************
*  Called when the value of the time spin box changes.
*/
void TimePeriod::slotTimeChanged(int value)
{
	if (mHourMinuteRaised)
		emit valueChanged(value);
}

/******************************************************************************
 * Set the currently displayed count widget.
 */
void TimePeriod::showHourMin(bool hourMinute)
{
	if (hourMinute != mHourMinuteRaised)
	{
		mHourMinuteRaised = hourMinute;
		if (hourMinute)
		{
			mSpinStack->raiseWidget(mTimeSpinBox);
			mSpinStack->setFocusProxy(mTimeSpinBox);
		}
		else
		{
			mSpinStack->raiseWidget(mSpinBox);
			mSpinStack->setFocusProxy(mSpinBox);
		}
	}
}

/******************************************************************************
 * Set separate WhatsThis texts for the count spinboxes and the units combobox.
 * If the hours:minutes text is omitted, both spinboxes are set to the same
 * WhatsThis text.
 */
void TimePeriod::setWhatsThis(const QString& units, const QString& dayWeek, const QString& hourMin)
{
	QWhatsThis::add(mUnitsCombo, units);
	QWhatsThis::add(mSpinBox, dayWeek);
	QWhatsThis::add(mTimeSpinBox, (hourMin.isNull() ? dayWeek : hourMin));
}
<commit_msg>Fix compile warning<commit_after>/*
 *  timeperiod.h  -  time period data entry widget
 *  Program:  kalarm
 *  (C) 2003, 2004 by David Jarvie <software@astrojar.org.uk>
 *
 *  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

#include "kalarm.h"

#include <qwidgetstack.h>
#include <qwhatsthis.h>

#include <klocale.h>
#include <kdialog.h>

#include "combobox.h"
#include "spinbox.h"
#include "timespinbox.h"
#include "timeperiod.moc"

// Collect these widget labels together to ensure consistent wording and
// translations across different modules.
QString TimePeriod::i18n_hours_mins()   { return i18n("hours/minutes"); }
QString TimePeriod::i18n_Hours_Mins()   { return i18n("Hours/Minutes"); }
QString TimePeriod::i18n_days()         { return i18n("days"); }
QString TimePeriod::i18n_Days()         { return i18n("Days"); }
QString TimePeriod::i18n_weeks()        { return i18n("weeks"); }
QString TimePeriod::i18n_Weeks()        { return i18n("Weeks"); }

static const int maxMinutes = 100*60-1;   // absolute maximum value for hours:minutes = 99H59M

/*=============================================================================
= Class TimePeriod
= Contains a time unit combo box, plus a time spinbox, to select a time period.
=============================================================================*/

TimePeriod::TimePeriod(bool allowHourMinute, QWidget* parent, const char* name)
	: QHBox(parent, name),
	  mMaxDays(9999),
	  mNoHourMinute(!allowHourMinute),
	  mReadOnly(false)
{
	setSpacing(KDialog::spacingHint());

	mSpinStack = new QWidgetStack(this);
	mSpinBox = new SpinBox(mSpinStack);
	mSpinBox->setLineStep(1);
	mSpinBox->setLineShiftStep(10);
	mSpinBox->setRange(1, mMaxDays);
	connect(mSpinBox, SIGNAL(valueChanged(int)), SLOT(slotDaysChanged(int)));
	mSpinStack->addWidget(mSpinBox, 0);

	mTimeSpinBox = new TimeSpinBox(0, 99999, mSpinStack);
	mTimeSpinBox->setRange(1, maxMinutes);    // max 99H59M
	connect(mTimeSpinBox, SIGNAL(valueChanged(int)), SLOT(slotTimeChanged(int)));
	mSpinStack->addWidget(mTimeSpinBox, 1);

	mSpinStack->setFixedSize(mSpinBox->sizeHint().expandedTo(mTimeSpinBox->sizeHint()));
	mHourMinuteRaised = mNoHourMinute;
	showHourMin(!mNoHourMinute);

	mUnitsCombo = new ComboBox(false, this);
	if (mNoHourMinute)
		mDateOnlyOffset = 1;
	else
	{
		mDateOnlyOffset = 0;
		mUnitsCombo->insertItem(i18n_hours_mins());
	}
	mUnitsCombo->insertItem(i18n_days());
	mUnitsCombo->insertItem(i18n_weeks());
	mMaxUnitShown = WEEKS;
	mUnitsCombo->setFixedSize(mUnitsCombo->sizeHint());
	connect(mUnitsCombo, SIGNAL(activated(int)), SLOT(slotUnitsSelected(int)));

	setFocusProxy(mUnitsCombo);
	setTabOrder(mUnitsCombo, mSpinStack);
}

void TimePeriod::setReadOnly(bool ro)
{
	if (ro != mReadOnly)
	{
		mReadOnly = ro;
		mSpinBox->setReadOnly(ro);
		mTimeSpinBox->setReadOnly(ro);
		mUnitsCombo->setReadOnly(ro);
	}
}

/******************************************************************************
*  Set whether the editor text is to be selected whenever spin buttons are
*  clicked. Default is to select them.
*/
void TimePeriod::setSelectOnStep(bool sel)
{
	mSpinBox->setSelectOnStep(sel);
	mTimeSpinBox->setSelectOnStep(sel);
}

/******************************************************************************
*  Set the input focus on the count field.
*/
void TimePeriod::setFocusOnCount()
{
	mSpinStack->setFocus();
}

/******************************************************************************
*  Set the maximum values for the hours:minutes and days/weeks spinboxes.
*  If 'hourmin' = 0, the hours:minutes maximum is left unchanged.
*/
void TimePeriod::setMaximum(int hourmin, int days)
{
	int oldmins = minutes();
	if (hourmin > 0)
	{
		if (hourmin > maxMinutes)
			hourmin = maxMinutes;
		mTimeSpinBox->setRange(1, hourmin);
	}
	mMaxDays = (days >= 0) ? days : 0;
	adjustDayWeekShown();
	setUnitRange();
	int mins = minutes();
	if (mins != oldmins)
		emit valueChanged(mins);
}

/******************************************************************************
 * Get the specified number of minutes.
 * Reply = 0 if error.
 */
int TimePeriod::minutes() const
{
	switch (mUnitsCombo->currentItem() + mDateOnlyOffset)
	{
		case HOURS_MINUTES:
			return mTimeSpinBox->value();
		case DAYS:
			return mSpinBox->value() * 24*60;
		case WEEKS:
			return mSpinBox->value() * 7*24*60;
	}
	return 0;
}

/******************************************************************************
*  Initialise the controls with a specified time period.
*  The time unit combo-box is initialised to 'defaultUnits', but if 'dateOnly'
*  is true, it will never be initialised to hours/minutes.
*/
void TimePeriod::setMinutes(int mins, bool dateOnly, TimePeriod::Units defaultUnits)
{
	int oldmins = minutes();
	if (!dateOnly  &&  mNoHourMinute)
		dateOnly = true;
	int item;
	if (mins)
	{
		int count = mins;
		if (mins % (24*60))
			item = HOURS_MINUTES;
		else if (mins % (7*24*60))
		{
			item = DAYS;
			count = mins / (24*60);
		}
		else
		{
			item = WEEKS;
			count = mins / (7*24*60);
		}
		if (item < mDateOnlyOffset)
			item = mDateOnlyOffset;
		else if (item > mMaxUnitShown)
			item = mMaxUnitShown;
		mUnitsCombo->setCurrentItem(item - mDateOnlyOffset);
		if (item == HOURS_MINUTES)
			mTimeSpinBox->setValue(count);
		else
			mSpinBox->setValue(count);
		item = setDateOnly(mins, dateOnly, false);
	}
	else
	{
		item = defaultUnits;
		if (item < mDateOnlyOffset)
			item = mDateOnlyOffset;
		else if (item > mMaxUnitShown)
			item = mMaxUnitShown;
		mUnitsCombo->setCurrentItem(item - mDateOnlyOffset);
		if (dateOnly && !mDateOnlyOffset  ||  !dateOnly && mDateOnlyOffset)
			item = setDateOnly(mins, dateOnly, false);
	}
	showHourMin(item == HOURS_MINUTES  &&  !mNoHourMinute);

	int newmins = minutes();
	if (newmins != oldmins)
		emit valueChanged(newmins);
}

/******************************************************************************
*  Enable/disable hours/minutes units (if hours/minutes were permitted in the
*  constructor).
*/
TimePeriod::Units TimePeriod::setDateOnly(int mins, bool dateOnly, bool signal)
{
	int oldmins = 0;
	if (signal)
		oldmins = minutes();
	int index = mUnitsCombo->currentItem();
	Units units = static_cast<Units>(index + mDateOnlyOffset);
	if (!mNoHourMinute)
	{
		if (!dateOnly  &&  mDateOnlyOffset)
		{
			// Change from date-only to allow hours/minutes
			mUnitsCombo->insertItem(i18n_hours_mins(), 0);
			mDateOnlyOffset = 0;
			adjustDayWeekShown();
			mUnitsCombo->setCurrentItem(++index);
		}
		else if (dateOnly  &&  !mDateOnlyOffset)
		{
			// Change from allowing hours/minutes to date-only
			mUnitsCombo->removeItem(0);
			mDateOnlyOffset = 1;
			if (index)
				--index;
			adjustDayWeekShown();
			mUnitsCombo->setCurrentItem(index);
			if (units == HOURS_MINUTES)
			{
				// Set units to days and round up the warning period
				units = DAYS;
				mUnitsCombo->setCurrentItem(DAYS - mDateOnlyOffset);
				mSpinBox->setValue((mins + 1439) / 1440);
			}
			showHourMin(false);
		}
	}

	if (signal)
	{
		int newmins = minutes();
		if (newmins != oldmins)
			emit valueChanged(newmins);
	}
	return units;
}

/******************************************************************************
*  Adjust the days/weeks units shown to suit the maximum days limit.
*/
void TimePeriod::adjustDayWeekShown()
{
	Units newMaxUnitShown = (mMaxDays >= 7) ? WEEKS : (mMaxDays || mDateOnlyOffset) ? DAYS : HOURS_MINUTES;
	if (newMaxUnitShown > mMaxUnitShown)
	{
		if (mMaxUnitShown < DAYS)
			mUnitsCombo->insertItem(i18n_days());
		if (newMaxUnitShown == WEEKS)
			mUnitsCombo->insertItem(i18n_weeks());
	}
	else if (newMaxUnitShown < mMaxUnitShown)
	{
		if (mMaxUnitShown == WEEKS)
			mUnitsCombo->removeItem(WEEKS - mDateOnlyOffset);
		if (newMaxUnitShown < DAYS)
			mUnitsCombo->removeItem(DAYS - mDateOnlyOffset);
	}
	mMaxUnitShown = newMaxUnitShown;
}

/******************************************************************************
*  Set the maximum value which may be entered into the day/week count field,
*  depending on the current unit selection.
*/
void TimePeriod::setUnitRange()
{
	int maxval;
	switch (static_cast<Units>(mUnitsCombo->currentItem() + mDateOnlyOffset))
	{
		case WEEKS:
			maxval = mMaxDays / 7;
			if (maxval)
				break;
			mUnitsCombo->setCurrentItem(DAYS - mDateOnlyOffset);
			// fall through to DAYS
		case DAYS:
			maxval = mMaxDays ? mMaxDays : 1;
			break;
		case HOURS_MINUTES:
		default:
			return;
	}
	mSpinBox->setRange(1, maxval);
}

/******************************************************************************
*  Called when a new item is made current in the time units combo box.
*/
void TimePeriod::slotUnitsSelected(int index)
{
	setUnitRange();
	showHourMin(index + mDateOnlyOffset == HOURS_MINUTES);
	emit valueChanged(minutes());
}

/******************************************************************************
*  Called when the value of the days/weeks spin box changes.
*/
void TimePeriod::slotDaysChanged(int)
{
	if (!mHourMinuteRaised)
		emit valueChanged(minutes());
}

/******************************************************************************
*  Called when the value of the time spin box changes.
*/
void TimePeriod::slotTimeChanged(int value)
{
	if (mHourMinuteRaised)
		emit valueChanged(value);
}

/******************************************************************************
 * Set the currently displayed count widget.
 */
void TimePeriod::showHourMin(bool hourMinute)
{
	if (hourMinute != mHourMinuteRaised)
	{
		mHourMinuteRaised = hourMinute;
		if (hourMinute)
		{
			mSpinStack->raiseWidget(mTimeSpinBox);
			mSpinStack->setFocusProxy(mTimeSpinBox);
		}
		else
		{
			mSpinStack->raiseWidget(mSpinBox);
			mSpinStack->setFocusProxy(mSpinBox);
		}
	}
}

/******************************************************************************
 * Set separate WhatsThis texts for the count spinboxes and the units combobox.
 * If the hours:minutes text is omitted, both spinboxes are set to the same
 * WhatsThis text.
 */
void TimePeriod::setWhatsThis(const QString& units, const QString& dayWeek, const QString& hourMin)
{
	QWhatsThis::add(mUnitsCombo, units);
	QWhatsThis::add(mSpinBox, dayWeek);
	QWhatsThis::add(mTimeSpinBox, (hourMin.isNull() ? dayWeek : hourMin));
}
<|endoftext|>


<commit_before>/* -*- mode:C++; -*- */
/* MIT License -- MyThOS: The Many-Threads Operating System
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 * Copyright 2014 Randolf Rotta, Maik Krüger, and contributors, BTU Cottbus-Senftenberg
 */
#include "cpu/LAPIC.hh"
#include "cpu/hwthread_pause.hh"
#include "cpu/ctrlregs.hh"
#include "boot/mlog.hh"
#include "util/assert.hh"

namespace mythos {
  LAPIC lapic;

  void LAPIC::init() {
    MLOG_DETAIL(mlog::boot, "initializing local xAPIC");
    Register value;

    // init the Destination Format Register and the Logical
    // Destination Register Intel recommends to set DFR, LDR and TPR
    // before enabling an APIC.  See e.g. "AP-388 82489DX User's
    // Manual" (Intel document number 292116).
    value = read(REG_DFR);
    MLOG_DETAIL(mlog::boot, "APIC DFR", DVARhex(value.value));
    value.model = 0xF; // flat mode
    write(REG_DFR, value);
    value = read(REG_LDR);
    MLOG_DETAIL(mlog::boot, "APIC LDR", DVARhex(value.value));
    value.destination = 1; // will not be used anyway
    write(REG_LDR, value);

    // init the local interrupt sources
    // all of them should be in invalid state anyway
    value.value = 0;
    value.masked = 1;
    write(REG_LVT_TIMER, value);
    write(REG_LVT_THERMAL, value);
    write(REG_LVT_PERFCNT, value);
    write(REG_LVT_LINT0, value);
    write(REG_LVT_LINT1, value);
    write(REG_LVT_ERROR, value);

    // enable all interrupts by task priority 0
    // see 10.8.6 Task Priority in IA-32e Mode
    // Loading the TPR with a task-priority class of 0 enables all external interrupts.
    // Loading the TPR with a task-priority class of 0FH (01111B) disables all external interrupts.
    // In 64-bit mode, software can read and write the TPR using the MOV CR8 instruction.
    value = read(REG_TASK_PRIO);
    value.task_prio_sub = 0;
    value.task_prio = 0;
    write(REG_TASK_PRIO, value);

    // After a crash, interrupts from previous run can still have ISR bit set.
    // Thus clear these with EndOfInterrupt.
    size_t queued = 0;
    for (size_t loops=0; loops<1000000; loops++) {
      for (size_t i=0; i<0x8; i++) queued |= read(REG_IRR + i*0x10).value;
      if (!queued) break;
      for (size_t i=0; i<0x8; i++) {
	value = read(REG_ISR + i*0x10);
	for (size_t j=0; j<32; j++) {
	  if (value.value & (1<<j)) endOfInterrupt();
	}
      }
    }

    // init the Spurious Interrupt Vector Register for handling local interrupt sources
    // after the reset SPURINT == 0xFF, setting bit 8 enables the APIC, for example 0x100
    // the lowest 4 bits should be 0, the vector should be above 32 (processor internal interrupts)
    // but the acutal value does not matter, because it is configured for each separately...
    value = read(REG_SVR);
    MLOG_DETAIL(mlog::boot, "SVR before init", reinterpret_cast<void*>(value.value));
    value.vector = 0xFF;  // this interrupt should never be triggered anyway
    value.apic_enable = 1;
    value.focus_processor_checking = 0;
    value.eio_suppression = 0;
    MLOG_DETAIL(mlog::boot, "SVR writing", reinterpret_cast<void*>(value.value));
    write(REG_SVR, value);
    MLOG_DETAIL(mlog::boot, "SVR after init", reinterpret_cast<void*>(read(REG_SVR).value));

    MLOG_DETAIL(mlog::boot, "lapic", DVAR(x86::initialApicID()), DVAR(getId()));
    ASSERT(getId() == x86::initialApicID());

    // init Error register
    write(REG_ESR, 0); read(REG_ESR); // Due to the Pentium erratum 3AP.
    value = read(REG_LVT_ERROR);
    value.vector = 0xFF; // should never happen because we leave it masked
    value.masked = 1;
    write(REG_LVT_ERROR, value);
    // spec says clear errors after enabling vector.
    write(REG_ESR, 0); read(REG_ESR); // Due to the Pentium erratum 3AP.
  }

  void LAPIC::enablePeriodicTimer(uint8_t irq, uint32_t count) {
    MLOG_INFO(mlog::boot, "enable periodic APIC timer", DVAR(irq), DVAR(count));
    write(REG_TIMER_DCR, 0x0b);  // divide bus clock by 0xa=128 or 0xb=1
    setInitialCount(count);
    write(REG_LVT_TIMER, read(REG_LVT_TIMER).timer_mode(PERIODIC).masked(0).vector(irq));
  }

  void LAPIC::disableTimer() {
    MLOG_INFO(mlog::boot, "disable APIC timer");
    write(REG_LVT_TIMER, read(REG_LVT_TIMER).timer_mode(ONESHOT).masked(1).vector(0));
  }

  bool LAPIC::broadcastInitIPIEdge() {
    write(REG_ESR, 0); // Be paranoid about clearing APIC errors.
    read(REG_ESR);
    writeIPI(0, edgeIPI(ICR_DESTSHORT_NOTSELF, MODE_INIT, 0));
    //hwthread_wait(10000);
    return true;
  }

  bool LAPIC::broadcastStartupIPI(size_t startIP) {
    ASSERT((startIP & 0x0FFF) == 0 && ((startIP>>12)>>8) == 0);
    write(REG_ESR, 0); // Be paranoid about clearing APIC errors.
    read(REG_ESR);
    writeIPI(0, edgeIPI(ICR_DESTSHORT_NOTSELF, MODE_SIPI, uint8_t(startIP >> 12)));
    write(REG_ESR, 0); // Be paranoid about clearing APIC errors.
    uint32_t esr = read(REG_ESR).value & 0xEF;
    MLOG_DETAIL(mlog::boot, "SIPI broadcast result", DVARhex(esr));
    return true;
  }

  bool LAPIC::sendNMI(size_t destination) {
    write(REG_ESR, 0); // Be paranoid about clearing APIC errors.
    read(REG_ESR);
    writeIPI(destination, edgeIPI(ICR_DESTSHORT_NO, MODE_NMI, 0));
    write(REG_ESR, 0); // Be paranoid about clearing APIC errors.
    return true;
  }

  bool LAPIC::sendIRQ(size_t destination, uint8_t vector)
  {
    MLOG_INFO(mlog::boot, "send IRQ:", DVAR(destination), DVAR(vector));
    //write(REG_ESR, 0); // Be paranoid about clearing APIC errors.
    //read(REG_ESR);
    writeIPI(destination, edgeIPI(ICR_DESTSHORT_NO, MODE_FIXED, vector));
    //write(REG_ESR, 0); // Be paranoid about clearing APIC errors.
    return true;
  }

  void LAPIC::writeIPI(size_t destination, Register icrlow) {
    ASSERT(destination<256);
    MLOG_DETAIL(mlog::boot, "write ICR", DVAR(destination), DVARhex(icrlow.value));

    while(read(REG_ICR_LOW).delivery_pending) hwthread_pause();

    write(REG_ICR_HIGH, Register().destination(destination));
    write(REG_ICR_LOW, icrlow);
  }

} // namespace mythos
<commit_msg>Quick fix and documentation.<commit_after>/* -*- mode:C++; -*- */
/* MIT License -- MyThOS: The Many-Threads Operating System
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 * Copyright 2014 Randolf Rotta, Maik Krüger, and contributors, BTU Cottbus-Senftenberg
 */
#include "cpu/LAPIC.hh"
#include "cpu/hwthread_pause.hh"
#include "cpu/ctrlregs.hh"
#include "boot/mlog.hh"
#include "util/assert.hh"

namespace mythos {
  LAPIC lapic;

  void LAPIC::init() {
    MLOG_DETAIL(mlog::boot, "initializing local xAPIC");
    Register value;

    // init the Destination Format Register and the Logical
    // Destination Register Intel recommends to set DFR, LDR and TPR
    // before enabling an APIC.  See e.g. "AP-388 82489DX User's
    // Manual" (Intel document number 292116).
    value = read(REG_DFR);
    MLOG_DETAIL(mlog::boot, "APIC DFR", DVARhex(value.value));
    value.model = 0xF; // flat mode
    write(REG_DFR, value);
    value = read(REG_LDR);
    MLOG_DETAIL(mlog::boot, "APIC LDR", DVARhex(value.value));
    value.destination = 1; // will not be used anyway
    write(REG_LDR, value);

    // init the local interrupt sources
    // all of them should be in invalid state anyway
    value.value = 0;
    value.masked = 1;
    write(REG_LVT_TIMER, value);
    write(REG_LVT_THERMAL, value);
    write(REG_LVT_PERFCNT, value);
    write(REG_LVT_LINT0, value);
    write(REG_LVT_LINT1, value);
    write(REG_LVT_ERROR, value);

    // enable all interrupts by task priority 0
    // see 10.8.6 Task Priority in IA-32e Mode
    // Loading the TPR with a task-priority class of 0 enables all external interrupts.
    // Loading the TPR with a task-priority class of 0FH (01111B) disables all external interrupts.
    // In 64-bit mode, software can read and write the TPR using the MOV CR8 instruction.
    value = read(REG_TASK_PRIO);
    value.task_prio_sub = 0;
    value.task_prio = 0;
    write(REG_TASK_PRIO, value);

    // After a crash, interrupts from previous run can still have ISR bit set.
    // Thus clear these with EndOfInterrupt.
    size_t queued = 0;
    for (size_t loops=0; loops<1000000; loops++) {
      for (size_t i=0; i<0x8; i++) queued |= read(REG_IRR + i*0x10).value;
      if (!queued) break;
      for (size_t i=0; i<0x8; i++) {
	value = read(REG_ISR + i*0x10);
	for (size_t j=0; j<32; j++) {
	  if (value.value & (1<<j)) endOfInterrupt();
	}
      }
    }

    // init the Spurious Interrupt Vector Register for handling local interrupt sources
    // after the reset SPURINT == 0xFF, setting bit 8 enables the APIC, for example 0x100
    // the lowest 4 bits should be 0, the vector should be above 32 (processor internal interrupts)
    // but the acutal value does not matter, because it is configured for each separately...
    value = read(REG_SVR);
    MLOG_DETAIL(mlog::boot, "SVR before init", reinterpret_cast<void*>(value.value));
    value.vector = 0xFF;  // this interrupt should never be triggered anyway
    value.apic_enable = 1;
    value.focus_processor_checking = 0;
    value.eio_suppression = 0;
    MLOG_DETAIL(mlog::boot, "SVR writing", reinterpret_cast<void*>(value.value));
    write(REG_SVR, value);
    MLOG_DETAIL(mlog::boot, "SVR after init", reinterpret_cast<void*>(read(REG_SVR).value));

    MLOG_DETAIL(mlog::boot, "lapic", DVAR(x86::initialApicID()), DVAR(getId()));
    ASSERT(getId() == x86::initialApicID());

    // init Error register
    write(REG_ESR, 0); read(REG_ESR); // Due to the Pentium erratum 3AP.
    value = read(REG_LVT_ERROR);
    value.vector = 0xFF; // should never happen because we leave it masked
    value.masked = 1;
    write(REG_LVT_ERROR, value);
    // spec says clear errors after enabling vector.
    write(REG_ESR, 0); read(REG_ESR); // Due to the Pentium erratum 3AP.
  }

  void LAPIC::enablePeriodicTimer(uint8_t irq, uint32_t count) {
    MLOG_INFO(mlog::boot, "enable periodic APIC timer", DVAR(irq), DVAR(count));
    write(REG_TIMER_DCR, 0x0b);  // divide bus clock by 0xa=128 or 0xb=1
    setInitialCount(count);
    write(REG_LVT_TIMER, read(REG_LVT_TIMER).timer_mode(PERIODIC).masked(0).vector(irq));
  }

  void LAPIC::disableTimer() {
    MLOG_INFO(mlog::boot, "disable APIC timer");
    write(REG_LVT_TIMER, read(REG_LVT_TIMER).timer_mode(ONESHOT).masked(1).vector(0));
  }

  bool LAPIC::broadcastInitIPIEdge() {
    write(REG_ESR, 0); // Be paranoid about clearing APIC errors.
    read(REG_ESR);
    writeIPI(0, edgeIPI(ICR_DESTSHORT_NOTSELF, MODE_INIT, 0));
    /**
     * This delay must happen between `broadcastInitIPIEdge` and
     * `broadcastStartupIPI` in order for all hardware threads to
     * start on the real hardware (KNC).
     *
     * @todo How long should this delay be for a given architecture.
     * @todo Move the delay out of this low level function.
     */
    hwthread_wait(10000);
    return true;
  }

  bool LAPIC::broadcastStartupIPI(size_t startIP) {
    ASSERT((startIP & 0x0FFF) == 0 && ((startIP>>12)>>8) == 0);
    write(REG_ESR, 0); // Be paranoid about clearing APIC errors.
    read(REG_ESR);
    writeIPI(0, edgeIPI(ICR_DESTSHORT_NOTSELF, MODE_SIPI, uint8_t(startIP >> 12)));
    write(REG_ESR, 0); // Be paranoid about clearing APIC errors.
    uint32_t esr = read(REG_ESR).value & 0xEF;
    MLOG_DETAIL(mlog::boot, "SIPI broadcast result", DVARhex(esr));
    return true;
  }

  bool LAPIC::sendNMI(size_t destination) {
    write(REG_ESR, 0); // Be paranoid about clearing APIC errors.
    read(REG_ESR);
    writeIPI(destination, edgeIPI(ICR_DESTSHORT_NO, MODE_NMI, 0));
    write(REG_ESR, 0); // Be paranoid about clearing APIC errors.
    return true;
  }

  bool LAPIC::sendIRQ(size_t destination, uint8_t vector)
  {
    MLOG_INFO(mlog::boot, "send IRQ:", DVAR(destination), DVAR(vector));
    //write(REG_ESR, 0); // Be paranoid about clearing APIC errors.
    //read(REG_ESR);
    writeIPI(destination, edgeIPI(ICR_DESTSHORT_NO, MODE_FIXED, vector));
    //write(REG_ESR, 0); // Be paranoid about clearing APIC errors.
    return true;
  }

  void LAPIC::writeIPI(size_t destination, Register icrlow) {
    ASSERT(destination<256);
    MLOG_DETAIL(mlog::boot, "write ICR", DVAR(destination), DVARhex(icrlow.value));

    while(read(REG_ICR_LOW).delivery_pending) hwthread_pause();

    write(REG_ICR_HIGH, Register().destination(destination));
    write(REG_ICR_LOW, icrlow);
  }

} // namespace mythos
<|endoftext|>


<commit_before>// This file is part of BlueSky
//
// BlueSky is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// BlueSky 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 BlueSky; if not, see <http://www.gnu.org/licenses/>.

//
// C++ Implementation: bs_kernel_ston
//
// Description:
//
//
// Author: Гагарин Александр Владимирович <GagarinAV@ufanipi.ru>, (C) 2008
//
#include "bs_kernel.h"
#include "thread_pool.h"
#include "bs_report.h"
#include "bs_log_scribers.h"

//#define LOKI_CLASS_LEVEL_THREADING
#include "loki/Singleton.h"

using namespace Loki;
using namespace std;

namespace blue_sky { namespace bs_private {

static bool kernel_alive = false;

/*-----------------------------------------------------------------------------
 *  Specific logging system wrappers
 *-----------------------------------------------------------------------------*/
struct bs_log_wrapper : public bs_log
{
	bs_log_wrapper ()
	{
		if (kernel_alive)
		{
			register_signals ();
		}

		this->add_channel (sp_channel (new bs_channel (OUT_LOG)));
		this->add_channel (sp_channel (new bs_channel (ERR_LOG)));

		char *c_dir = NULL;
		if (!(c_dir = getenv("BS_KERNEL_DIR")))
			c_dir = (char *)".";

		this->get_locked (OUT_LOG).get_channel ()->attach(sp_stream(new log::detail::cout_scriber));
		this->get_locked (OUT_LOG).get_channel ()->attach(sp_stream(new log::detail::file_scriber (string(c_dir) + string("/blue_sky.log"), ios::out|ios::app)));
		this->get_locked (ERR_LOG).get_channel ()->attach(sp_stream(new log::detail::cout_scriber));
		this->get_locked (ERR_LOG).get_channel ()->attach(sp_stream(new log::detail::file_scriber (string(c_dir) + string("/errors.log"), ios::out|ios::app)));

		this->get_locked (OUT_LOG) << output_time;
		this->get_locked (ERR_LOG) << output_time;
	}

	//static bool &
	//kernel_dead ()
	//{
	//	static bool kernel_dead_ = false;

	//	return kernel_dead_;
	//}

	bs_log &
	get_log ()
	{
		return *this;
	}

	void
	register_signals ()
	{
		this->add_signal (BS_SIGNAL_RANGE (bs_log));
	}
};

struct thread_log_wrapper : public thread_log
{
	thread_log_wrapper ()
	{
	}

	thread_log &
	get_log ()
	{
		return *this;
	}

	void
	register_signals ()
	{
	}

	//static bool &
	//kernel_dead ()
	//{
	//	static bool kernel_dead_ = false;

	//	return kernel_dead_;
	//}
};

/// @brief Wrapper allowing to do some initialization on first give_kernel()::Instance() call
/// just after the kernel class is created
struct wrapper_kernel {

	 kernel* k_;

	 kernel& (wrapper_kernel::*ref_fun_)();

	 // constructor
	 wrapper_kernel()
		 : k_(new kernel), ref_fun_(&wrapper_kernel::initial_kernel_getter)
	 {
		 kernel_alive = true;
	 }

	 // normal getter - just returns kernel reference
	 kernel& usual_kernel_getter() {
		 return *k_;
	 }

	 // when kernel reference is obtained for the first time
	 kernel& initial_kernel_getter() {
		 // first switch to usual getter to avoid infinite constructor recursion during load_plugins()
		 ref_fun_ = &wrapper_kernel::usual_kernel_getter;
		 // initialize kernel
		 k_->init();

#ifdef BS_AUTOLOAD_PLUGINS
		 // load plugins
		 k_->LoadPlugins();
#endif
		 // return reference
		 return *k_;
	 }

	 kernel& k_ref() {
		return (this->*ref_fun_)();
	 }

	 ~wrapper_kernel() {
		// force kernel destruction
		 delete k_;

		// signal that it is destroyed
		kernel_alive = false;

		//bs_log_wrapper::kernel_dead () = true;
		//thread_log_wrapper::kernel_dead () = true;
	 }
// 			 kernel& k_ref() {
// 				 return k_;
// 			 }
};

typedef SingletonHolder < bs_log_wrapper, CreateUsingNew, PhoenixSingleton >      bs_log_holder;
typedef SingletonHolder < thread_log_wrapper, CreateUsingNew, PhoenixSingleton >  thread_log_holder;

}	// namespace bs_private

/*-----------------------------------------------------------------------------
 *  kernel signleton instantiation
 *-----------------------------------------------------------------------------*/
//! multithreaded kernel singleton - disables
//typedef SingletonHolder< bs_private::wrapper_kernel, CreateUsingNew,
//	DefaultLifetime, ClassLevelLockable > kernel_holder;

// kernel itself is fully multithreaded so we can use simple singleton
// typedef SingletonHolder< bs_private::wrapper_kernel > kernel_holder;

//kernel singletone - master, fabs die after kernel dies
typedef SingletonHolder< bs_private::wrapper_kernel, CreateUsingNew,
	FollowIntoDeath::With< DefaultLifetime >::AsMasterLifetime > kernel_holder;

template< >
BS_API kernel& singleton< kernel >::Instance()
{
	//cout << "give_kernel.Instance() entered" << endl;
	return kernel_holder::Instance().k_ref();
}

//! thread pool singleton
typedef SingletonHolder< blue_sky::worker_thread_pool, CreateUsingNew,
	FollowIntoDeath::AfterMaster< kernel_holder >::IsDestroyed > wtp_holder;

typedef singleton< worker_thread_pool > give_wtp;

template< >
worker_thread_pool& singleton< worker_thread_pool >::Instance() {
	return wtp_holder::Instance();
}

//	void kernel::add_task(const blue_sky::sp_com& task)
//	{
//		give_wtp::Instance().add_command(task);
//	}

/*-----------------------------------------------------------------------------
 *  log singletons instantiation
 *-----------------------------------------------------------------------------*/
typedef singleton <bs_log>      bs_log_singleton;
typedef singleton <thread_log>  thread_log_singleton;

template <>
	bs_log &
singleton <bs_log>::Instance()
{
	return bs_private::bs_log_holder::Instance().get_log ();
}

template <>
	thread_log &
singleton <thread_log>::Instance ()
{
	return bs_private::thread_log_holder::Instance ().get_log ();
}

	bs_log &
kernel::get_log ()
{
	return bs_log_singleton::Instance ();
}

	thread_log &
kernel::get_tlog ()
{
	return thread_log_singleton::Instance ();
}

}	// namespace blue_sky

<commit_msg>-- Safer and simplier version of commit on 20 Aug 2009<commit_after>// This file is part of BlueSky
//
// BlueSky is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// BlueSky 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 BlueSky; if not, see <http://www.gnu.org/licenses/>.

//
// C++ Implementation: bs_kernel_ston
//
// Description:
//
//
// Author: Гагарин Александр Владимирович <GagarinAV@ufanipi.ru>, (C) 2008
//
#include "bs_kernel.h"
#include "thread_pool.h"
#include "bs_report.h"
#include "bs_log_scribers.h"

//#define LOKI_CLASS_LEVEL_THREADING
#include "loki/Singleton.h"

using namespace Loki;
using namespace std;

namespace blue_sky { namespace bs_private {

static bool kernel_alive = false;

/*-----------------------------------------------------------------------------
 *  Specific logging system wrappers
 *-----------------------------------------------------------------------------*/
struct bs_log_wrapper : public bs_log
{
	bs_log_wrapper ()
	{
		if (kernel_alive)
		{
			register_signals ();
		}

		this->add_channel (sp_channel (new bs_channel (OUT_LOG)));
		this->add_channel (sp_channel (new bs_channel (ERR_LOG)));

		char *c_dir = NULL;
		if (!(c_dir = getenv("BS_KERNEL_DIR")))
			c_dir = (char *)".";

		this->get_locked (OUT_LOG).get_channel ()->attach(sp_stream(new log::detail::cout_scriber));
		this->get_locked (OUT_LOG).get_channel ()->attach(sp_stream(new log::detail::file_scriber (string(c_dir) + string("/blue_sky.log"), ios::out|ios::app)));
		this->get_locked (ERR_LOG).get_channel ()->attach(sp_stream(new log::detail::cout_scriber));
		this->get_locked (ERR_LOG).get_channel ()->attach(sp_stream(new log::detail::file_scriber (string(c_dir) + string("/errors.log"), ios::out|ios::app)));

		this->get_locked (OUT_LOG) << output_time;
		this->get_locked (ERR_LOG) << output_time;
	}

	//static bool &
	//kernel_dead ()
	//{
	//	static bool kernel_dead_ = false;

	//	return kernel_dead_;
	//}

	bs_log &
	get_log ()
	{
		return *this;
	}

	void
	register_signals ()
	{
		this->add_signal (BS_SIGNAL_RANGE (bs_log));
	}
};

struct thread_log_wrapper : public thread_log
{
	thread_log_wrapper ()
	{
	}

	thread_log &
	get_log ()
	{
		return *this;
	}

	void
	register_signals ()
	{
	}

	//static bool &
	//kernel_dead ()
	//{
	//	static bool kernel_dead_ = false;

	//	return kernel_dead_;
	//}
};

/// @brief Wrapper allowing to do some initialization on first give_kernel()::Instance() call
/// just after the kernel class is created
struct wrapper_kernel {
	kernel k_;

	kernel& (wrapper_kernel::*ref_fun_)();

	// constructor
	wrapper_kernel()
		: ref_fun_(&wrapper_kernel::initial_kernel_getter)
	{
		kernel_alive = true;
	}

	// normal getter - just returns kernel reference
	kernel& usual_kernel_getter() {
		return k_;
	}

	// when kernel reference is obtained for the first time
	kernel& initial_kernel_getter() {
		// first switch to usual getter to avoid infinite constructor recursion during load_plugins()
		ref_fun_ = &wrapper_kernel::usual_kernel_getter;
		// initialize kernel
		k_.init();

#ifdef BS_AUTOLOAD_PLUGINS
		// load plugins
		k_.LoadPlugins();
#endif
		// return reference
		return k_;
	}

	kernel& k_ref() {
		return (this->*ref_fun_)();
	}

	~wrapper_kernel() {
		// signal that it is destroyed
		kernel_alive = false;

		//bs_log_wrapper::kernel_dead () = true;
		//thread_log_wrapper::kernel_dead () = true;
	}
	//kernel& k_ref() {
	//    return k_;
	//}
};

typedef SingletonHolder < bs_log_wrapper, CreateUsingNew, PhoenixSingleton >      bs_log_holder;
typedef SingletonHolder < thread_log_wrapper, CreateUsingNew, PhoenixSingleton >  thread_log_holder;

}	// namespace bs_private

/*-----------------------------------------------------------------------------
 *  kernel signleton instantiation
 *-----------------------------------------------------------------------------*/
//! multithreaded kernel singleton - disables
//typedef SingletonHolder< bs_private::wrapper_kernel, CreateUsingNew,
//	DefaultLifetime, ClassLevelLockable > kernel_holder;

// kernel itself is fully multithreaded so we can use simple singleton
// typedef SingletonHolder< bs_private::wrapper_kernel > kernel_holder;

//kernel singletone - master, fabs die after kernel dies
typedef SingletonHolder< bs_private::wrapper_kernel, CreateUsingNew,
	FollowIntoDeath::With< DefaultLifetime >::AsMasterLifetime > kernel_holder;

template< >
BS_API kernel& singleton< kernel >::Instance()
{
	//cout << "give_kernel.Instance() entered" << endl;
	return kernel_holder::Instance().k_ref();
}

//! thread pool singleton
typedef SingletonHolder< blue_sky::worker_thread_pool, CreateUsingNew,
	FollowIntoDeath::AfterMaster< kernel_holder >::IsDestroyed > wtp_holder;

typedef singleton< worker_thread_pool > give_wtp;

template< >
worker_thread_pool& singleton< worker_thread_pool >::Instance() {
	return wtp_holder::Instance();
}

//	void kernel::add_task(const blue_sky::sp_com& task)
//	{
//		give_wtp::Instance().add_command(task);
//	}

/*-----------------------------------------------------------------------------
 *  log singletons instantiation
 *-----------------------------------------------------------------------------*/
typedef singleton <bs_log>      bs_log_singleton;
typedef singleton <thread_log>  thread_log_singleton;

template <>
	bs_log &
singleton <bs_log>::Instance()
{
	return bs_private::bs_log_holder::Instance().get_log ();
}

template <>
	thread_log &
singleton <thread_log>::Instance ()
{
	return bs_private::thread_log_holder::Instance ().get_log ();
}

	bs_log &
kernel::get_log ()
{
	return bs_log_singleton::Instance ();
}

	thread_log &
kernel::get_tlog ()
{
	return thread_log_singleton::Instance ();
}

}	// namespace blue_sky

<|endoftext|>


<commit_before>/* Copyright 2009 Klarälvdalens Datakonsult AB

   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) version 3 or any later version
   accepted by the membership of KDE e.V. (or its successor approved
   by the membership of KDE e.V.), which shall act as a proxy
   defined in Section 14 of version 3 of the license.

   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, see <http://www.gnu.org/licenses/>.
*/
#include "importarchivedialog.h"

#include "kmfolder.h"
#include "folderrequester.h"
#include "kmmainwidget.h"
#include "importjob.h"

#include <kurlrequester.h>
#include <klocale.h>
#include <kmessagebox.h>

#include <qlayout.h>
#include <qlabel.h>

using namespace KMail;

ImportArchiveDialog::ImportArchiveDialog( QWidget *parent )
  : KDialog( parent ), mParentWidget( parent )
{
  setObjectName( "archive_folder_dialog" );
  setCaption( i18n( "Archive Folder" ) );
  setButtons( Ok|Cancel );
  setDefaultButton( Ok );
  setModal( true );
  QWidget *mainWidget = new QWidget( this );
  QGridLayout *mainLayout = new QGridLayout( mainWidget );
  mainLayout->setSpacing( KDialog::spacingHint() );
  mainLayout->setMargin( KDialog::marginHint() );
  setMainWidget( mainWidget );

  int row = 0;

  // TODO: Explaination label
  // TODO: Use QFormLayout in KDE4
  // TODO: better label for "Ok" button

  QLabel *folderLabel = new QLabel( i18n( "Folder:" ), mainWidget );
  mainLayout->addWidget( folderLabel, row, 0 );
  mFolderRequester = new FolderRequester( mainWidget );
  mFolderRequester->setFolderTree( kmkernel->getKMMainWidget()->mainFolderView() );
  mainLayout->addWidget( mFolderRequester, row, 1 );
  row++;

  QLabel *fileNameLabel = new QLabel( i18n( "Archive File:" ), mainWidget );
  mainLayout->addWidget( fileNameLabel, row, 0 );
  mUrlRequester = new KUrlRequester( mainWidget );
  mUrlRequester->setMode( KFile::LocalOnly );
  mUrlRequester->setFilter( "*.tar *.zip *.tar.gz *.tar.bz2" );
  mainLayout->addWidget( mUrlRequester, row, 1 );
  row++;

  // TODO: what's this, tooltips

  mainLayout->setColumnStretch( 1, 1 );
  mainLayout->addItem( new QSpacerItem( 1, 1, QSizePolicy::Expanding, QSizePolicy::Expanding ), row, 0 );

  // Make it a bit bigger, else the folder requester cuts off the text too early
  resize( 500, minimumSize().height() );
}

void ImportArchiveDialog::setFolder( KMFolder *defaultFolder )
{
  mFolderRequester->setFolder( defaultFolder );
}

void ImportArchiveDialog::slotOk()
{
  if ( !QFile::exists( mUrlRequester->url().path() ) ) {
    KMessageBox::information( this, i18n( "Please select an archive file that should be imported." ),
                              i18n( "No archive file selected" ) );
    return;
  }

  if ( !mFolderRequester->folder() ) {
    KMessageBox::information( this, i18n( "Please select the folder where the archive should be imported to." ),
                              i18n( "No target folder selected" ) );
    return;
  }

  // TODO: check if url is empty. or better yet, disable ok button until file is chosen

  ImportJob *importJob = new KMail::ImportJob( mParentWidget );
  importJob->setFile( mUrlRequester->url() );
  importJob->setRootFolder( mFolderRequester->folder() );
  importJob->start();
  accept();
}

#include "importarchivedialog.moc"
<commit_msg>SVN_MERGE Merged revisions 1048289 via svnmerge from  svn+ssh://tmcguire@svn.kde.org/home/kde/branches/kdepim/enterprise4/kdepim<commit_after>/* Copyright 2009 Klarälvdalens Datakonsult AB

   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) version 3 or any later version
   accepted by the membership of KDE e.V. (or its successor approved
   by the membership of KDE e.V.), which shall act as a proxy
   defined in Section 14 of version 3 of the license.

   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, see <http://www.gnu.org/licenses/>.
*/
#include "importarchivedialog.h"

#include "kmfolder.h"
#include "folderrequester.h"
#include "kmmainwidget.h"
#include "importjob.h"

#include <kurlrequester.h>
#include <klocale.h>
#include <kmessagebox.h>

#include <qlayout.h>
#include <qlabel.h>

using namespace KMail;

ImportArchiveDialog::ImportArchiveDialog( QWidget *parent )
  : KDialog( parent ), mParentWidget( parent )
{
  setObjectName( "import_archive_dialog" );
  setCaption( i18n( "Import Archive" ) );
  setButtons( Ok|Cancel );
  setDefaultButton( Ok );
  setModal( true );
  QWidget *mainWidget = new QWidget( this );
  QGridLayout *mainLayout = new QGridLayout( mainWidget );
  mainLayout->setSpacing( KDialog::spacingHint() );
  mainLayout->setMargin( KDialog::marginHint() );
  setMainWidget( mainWidget );

  int row = 0;

  // TODO: Explaination label
  // TODO: Use QFormLayout in KDE4
  // TODO: better label for "Ok" button

  QLabel *folderLabel = new QLabel( i18n( "Folder:" ), mainWidget );
  mainLayout->addWidget( folderLabel, row, 0 );
  mFolderRequester = new FolderRequester( mainWidget );
  mFolderRequester->setFolderTree( kmkernel->getKMMainWidget()->mainFolderView() );
  mainLayout->addWidget( mFolderRequester, row, 1 );
  row++;

  QLabel *fileNameLabel = new QLabel( i18n( "Archive File:" ), mainWidget );
  mainLayout->addWidget( fileNameLabel, row, 0 );
  mUrlRequester = new KUrlRequester( mainWidget );
  mUrlRequester->setMode( KFile::LocalOnly );
  mUrlRequester->setFilter( "*.tar *.zip *.tar.gz *.tar.bz2" );
  mainLayout->addWidget( mUrlRequester, row, 1 );
  row++;

  // TODO: what's this, tooltips

  mainLayout->setColumnStretch( 1, 1 );
  mainLayout->addItem( new QSpacerItem( 1, 1, QSizePolicy::Expanding, QSizePolicy::Expanding ), row, 0 );

  // Make it a bit bigger, else the folder requester cuts off the text too early
  resize( 500, minimumSize().height() );
}

void ImportArchiveDialog::setFolder( KMFolder *defaultFolder )
{
  mFolderRequester->setFolder( defaultFolder );
}

void ImportArchiveDialog::slotOk()
{
  if ( !QFile::exists( mUrlRequester->url().path() ) ) {
    KMessageBox::information( this, i18n( "Please select an archive file that should be imported." ),
                              i18n( "No archive file selected" ) );
    return;
  }

  if ( !mFolderRequester->folder() ) {
    KMessageBox::information( this, i18n( "Please select the folder where the archive should be imported to." ),
                              i18n( "No target folder selected" ) );
    return;
  }

  // TODO: check if url is empty. or better yet, disable ok button until file is chosen

  ImportJob *importJob = new KMail::ImportJob( mParentWidget );
  importJob->setFile( mUrlRequester->url() );
  importJob->setRootFolder( mFolderRequester->folder() );
  importJob->start();
  accept();
}

#include "importarchivedialog.moc"
<|endoftext|>


<commit_before>/* KPilot
**
** Copyright (C) 1998-2001 by Dan Pilone
** Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
**
** This is all of KPilot's config-handling stuff.
*/

/*
** 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 in a file called COPYING; if not, write to
** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
** MA 02110-1301, USA.
*/

/*
** Bug reports and questions can be sent to kde-pim@kde.org
*/

#include "options.h"

#include <stdlib.h>

#include <qlineedit.h>
#include <qcombobox.h>
#include <qcheckbox.h>

#include <kstandarddirs.h>
#include <kconfig.h>
#include <ksimpleconfig.h>
#include <kcmdlineargs.h>
#include <kmessagebox.h>
#include <kglobalsettings.h>

#include "kpilotSettings.h"
#include "kpilotConfig.h"

// This is a number indicating what configuration version
// we're dealing with. Whenever new configuration options are
// added that make it imperative for the user to take a
// look at the configuration of KPilot (for example the
// skipDB setting really needs user attention) we can change
// (increase) this number.
//
//
/* static */ const uint KPilotConfig::ConfigurationVersion = 443;

/* static */ int KPilotConfig::getConfigVersion()
{
	FUNCTIONSETUP;

	uint version = KPilotSettings::configVersion();

	if (version < ConfigurationVersion)
	{
		WARNINGKPILOT << "Config file has old version " << version << endl;
	}
	else
	{
#ifdef DEBUG
		DEBUGKPILOT << fname
			<< ": Config file has version " << version << endl;
#endif
	}

	return version;
}

/* static */ void KPilotConfig::updateConfigVersion()
{
	FUNCTIONSETUP;
	KPilotSettings::setConfigVersion( ConfigurationVersion );
}

/* static */ QString KPilotConfig::getDefaultDBPath()
{
	FUNCTIONSETUP;
	QString lastUser = KPilotSettings::userName();
	QString dbsubpath = CSL1("kpilot/DBBackup/");
	QString defaultDBPath = KGlobal::dirs()->
		saveLocation("data", dbsubpath + lastUser + CSL1("/"));
	return defaultDBPath;
}

/* static */ int KPilotConfig::getDebugLevel(KCmdLineArgs *p)
{
	FUNCTIONSETUP;

	if (p)
	{
		if (p->isSet("debug"))
		{
			debug_level = p->getOption("debug").toInt();
		}
	}

	return debug_level;
}

static QFont *thefont = 0L;

/* static */ const QFont & KPilotConfig::fixed()
{
	FUNCTIONSETUP;

	if (!thefont)
		thefont = new QFont(KGlobalSettings::fixedFont());

	return *thefont;
}

void KPilotConfig::addDirtyDatabase(QString db)
{
	FUNCTIONSETUP;
	QStringList l(KPilotSettings::dirtyDatabases());
	if (!l.contains(db))
	{
		l.append(db);
		KPilotSettings::setDirtyDatabases(l);
	}
}

void KPilotConfig::addAppBlockChangedDatabase(QString db)
{
	QStringList l(KPilotSettings::appBlockChangedDatabases());
	if (!l.contains(db))
	{
		l.append(db);
		KPilotSettings::setAppBlockChangedDatabases(l);
	}
}

void KPilotConfig::addFlagsChangedDatabase(QString db)
{
	QStringList l(KPilotSettings::flagsChangedDatabases());
	if (!l.contains(db))
	{
		l.append(db);
		KPilotSettings::setFlagsChangedDatabases(l);
	}
}

/* static */ QString KPilotConfig::versionDetails(int fileversion, bool run)
{
	FUNCTIONSETUP;
	QString s = CSL1("<qt>
");
	s += i18n("The configuration file is outdated.");
	s += ' ';
	s += i18n("The configuration file has version %1, while KPilot "
		"needs version %2.").arg(fileversion).arg(ConfigurationVersion);
	if (run)
	{
		s += ' ';
		s += i18n("Please run KPilot and check the configuration carefully "
			"to update the file.");
	}
	s += CSL1("

");
	s += i18n("Important changes to watch for are:");
	s += ' ';
	if (fileversion < 440)
	{
		s += i18n("Renamed conduits, Kroupware and file installer have "
			"been made conduits as well.");
		s += ' ';
		s += i18n("Conflict resolution is now a global setting.");
		s += ' ';
	}
	if (fileversion < 443)
	{
		s += i18n("Changed format of no-backup databases.");
		s += ' ';
	}
	// Insert more recent additions here

	return s;
}

/* static */ void KPilotConfig::sorryVersionOutdated(int fileversion)
{
	FUNCTIONSETUP;
	KMessageBox::detailedSorry(0L,
		i18n("The configuration file for KPilot is out-of "
			"date. Please run KPilot to update it."),
		KPilotConfig::versionDetails(fileversion,true),
		i18n("Configuration File Out-of Date"));
}

/* static */ KPilotConfig::RunMode KPilotConfig::interactiveUpdate()
{
	FUNCTIONSETUP;

	int res = 0;
	unsigned int fileVersion = KPilotSettings::configVersion();
	// FIXME better config handling -> Move the config entries using kconf_update

	// It's OK if we're already at the required level.
	if (fileVersion >= KPilotConfig::ConfigurationVersion)
	{
		return Normal;
	}

	if (0 == fileVersion) // No config file at all
	{
		res = KMessageBox::questionYesNoCancel(0L,
			i18n("KPilot is not configured for use. You may use "
				"the configuration wizard or the normal configure dialog "
				"to configure KPilot."),
			i18n("Not Configured"),
			KGuiItem(i18n("Use &Wizard")),
			KGuiItem(i18n("Use &Dialog")));
		if (res == KMessageBox::Yes) return WizardAndContinue;
		if (res == KMessageBox::No) return ConfigureAndContinue;

		return Cancel;
	}

	res = KMessageBox::warningContinueCancel(0L,
		i18n("The configuration file for KPilot is out-of "
			"date. KPilot can update some parts of the "
			"configuration automatically. Do you wish to "
			"continue?"),
		i18n("Configuration File Out-of Date"));
	if (res!=KMessageBox::Continue) return Cancel;

	DEBUGKPILOT << fname << ": Updating from "
		<< fileVersion << " to " << ConfigurationVersion << endl;

	KPilotConfig::updateConfigVersion();
	KPilotSettings::writeConfig();
	return ConfigureAndContinue;
}

void KPilotConfig::sync()
{
	KPilotSettings::self()->config()->sync();
}
<commit_msg>Fix i18n<commit_after>/* KPilot
**
** Copyright (C) 1998-2001 by Dan Pilone
** Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
**
** This is all of KPilot's config-handling stuff.
*/

/*
** 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 in a file called COPYING; if not, write to
** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
** MA 02110-1301, USA.
*/

/*
** Bug reports and questions can be sent to kde-pim@kde.org
*/

#include "options.h"

#include <stdlib.h>

#include <qlineedit.h>
#include <qcombobox.h>
#include <qcheckbox.h>

#include <kstandarddirs.h>
#include <kconfig.h>
#include <ksimpleconfig.h>
#include <kcmdlineargs.h>
#include <kmessagebox.h>
#include <kglobalsettings.h>

#include "kpilotSettings.h"
#include "kpilotConfig.h"

// This is a number indicating what configuration version
// we're dealing with. Whenever new configuration options are
// added that make it imperative for the user to take a
// look at the configuration of KPilot (for example the
// skipDB setting really needs user attention) we can change
// (increase) this number.
//
//
/* static */ const uint KPilotConfig::ConfigurationVersion = 443;

/* static */ int KPilotConfig::getConfigVersion()
{
	FUNCTIONSETUP;

	uint version = KPilotSettings::configVersion();

	if (version < ConfigurationVersion)
	{
		WARNINGKPILOT << "Config file has old version " << version << endl;
	}
	else
	{
#ifdef DEBUG
		DEBUGKPILOT << fname
			<< ": Config file has version " << version << endl;
#endif
	}

	return version;
}

/* static */ void KPilotConfig::updateConfigVersion()
{
	FUNCTIONSETUP;
	KPilotSettings::setConfigVersion( ConfigurationVersion );
}

/* static */ QString KPilotConfig::getDefaultDBPath()
{
	FUNCTIONSETUP;
	QString lastUser = KPilotSettings::userName();
	QString dbsubpath = CSL1("kpilot/DBBackup/");
	QString defaultDBPath = KGlobal::dirs()->
		saveLocation("data", dbsubpath + lastUser + CSL1("/"));
	return defaultDBPath;
}

/* static */ int KPilotConfig::getDebugLevel(KCmdLineArgs *p)
{
	FUNCTIONSETUP;

	if (p)
	{
		if (p->isSet("debug"))
		{
			debug_level = p->getOption("debug").toInt();
		}
	}

	return debug_level;
}

static QFont *thefont = 0L;

/* static */ const QFont & KPilotConfig::fixed()
{
	FUNCTIONSETUP;

	if (!thefont)
		thefont = new QFont(KGlobalSettings::fixedFont());

	return *thefont;
}

void KPilotConfig::addDirtyDatabase(QString db)
{
	FUNCTIONSETUP;
	QStringList l(KPilotSettings::dirtyDatabases());
	if (!l.contains(db))
	{
		l.append(db);
		KPilotSettings::setDirtyDatabases(l);
	}
}

void KPilotConfig::addAppBlockChangedDatabase(QString db)
{
	QStringList l(KPilotSettings::appBlockChangedDatabases());
	if (!l.contains(db))
	{
		l.append(db);
		KPilotSettings::setAppBlockChangedDatabases(l);
	}
}

void KPilotConfig::addFlagsChangedDatabase(QString db)
{
	QStringList l(KPilotSettings::flagsChangedDatabases());
	if (!l.contains(db))
	{
		l.append(db);
		KPilotSettings::setFlagsChangedDatabases(l);
	}
}

/* static */ QString KPilotConfig::versionDetails(int fileversion, bool run)
{
	FUNCTIONSETUP;
	QString s = CSL1("<qt>
");
	s += i18n("The configuration file is outdated.");
	s += ' ';
	s += i18n("The configuration file has version %1, while KPilot "
		"needs version %2.",fileversion,ConfigurationVersion);
	if (run)
	{
		s += ' ';
		s += i18n("Please run KPilot and check the configuration carefully "
			"to update the file.");
	}
	s += CSL1("

");
	s += i18n("Important changes to watch for are:");
	s += ' ';
	if (fileversion < 440)
	{
		s += i18n("Renamed conduits, Kroupware and file installer have "
			"been made conduits as well.");
		s += ' ';
		s += i18n("Conflict resolution is now a global setting.");
		s += ' ';
	}
	if (fileversion < 443)
	{
		s += i18n("Changed format of no-backup databases.");
		s += ' ';
	}
	// Insert more recent additions here

	return s;
}

/* static */ void KPilotConfig::sorryVersionOutdated(int fileversion)
{
	FUNCTIONSETUP;
	KMessageBox::detailedSorry(0L,
		i18n("The configuration file for KPilot is out-of "
			"date. Please run KPilot to update it."),
		KPilotConfig::versionDetails(fileversion,true),
		i18n("Configuration File Out-of Date"));
}

/* static */ KPilotConfig::RunMode KPilotConfig::interactiveUpdate()
{
	FUNCTIONSETUP;

	int res = 0;
	unsigned int fileVersion = KPilotSettings::configVersion();
	// FIXME better config handling -> Move the config entries using kconf_update

	// It's OK if we're already at the required level.
	if (fileVersion >= KPilotConfig::ConfigurationVersion)
	{
		return Normal;
	}

	if (0 == fileVersion) // No config file at all
	{
		res = KMessageBox::questionYesNoCancel(0L,
			i18n("KPilot is not configured for use. You may use "
				"the configuration wizard or the normal configure dialog "
				"to configure KPilot."),
			i18n("Not Configured"),
			KGuiItem(i18n("Use &Wizard")),
			KGuiItem(i18n("Use &Dialog")));
		if (res == KMessageBox::Yes) return WizardAndContinue;
		if (res == KMessageBox::No) return ConfigureAndContinue;

		return Cancel;
	}

	res = KMessageBox::warningContinueCancel(0L,
		i18n("The configuration file for KPilot is out-of "
			"date. KPilot can update some parts of the "
			"configuration automatically. Do you wish to "
			"continue?"),
		i18n("Configuration File Out-of Date"));
	if (res!=KMessageBox::Continue) return Cancel;

	DEBUGKPILOT << fname << ": Updating from "
		<< fileVersion << " to " << ConfigurationVersion << endl;

	KPilotConfig::updateConfigVersion();
	KPilotSettings::writeConfig();
	return ConfigureAndContinue;
}

void KPilotConfig::sync()
{
	KPilotSettings::self()->config()->sync();
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: dicimp.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-07 19:50:36 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _LINGUISTIC_DICIMP_HXX_
#define _LINGUISTIC_DICIMP_HXX_

#include <com/sun/star/linguistic2/XDictionary1.hpp>
#include <com/sun/star/linguistic2/XDictionary.hpp>
#include <com/sun/star/frame/XStorable.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>

#include <uno/lbnames.h>            // CPPU_CURRENT_LANGUAGE_BINDING_NAME macro, which specify the environment type
#include <cppuhelper/implbase3.hxx> // helper for implementations
#include <cppuhelper/implbase1.hxx> // helper for implementations

#ifndef _CPPUHELPER_INTERFACECONTAINER_H_
#include <cppuhelper/interfacecontainer.h>
#endif

#ifndef _STRING_HXX
#include <tools/string.hxx>
#endif

#include "misc.hxx"

///////////////////////////////////////////////////////////////////////////

#define DIC_MAX_ENTRIES     2000

int             GetDicVersion( const sal_Char *pVerStr );
const String    GetDicExtension();

///////////////////////////////////////////////////////////////////////////

class DictionaryNeo :
    public ::cppu::WeakImplHelper3
    <
        ::com::sun::star::linguistic2::XDictionary1,
        ::com::sun::star::linguistic2::XDictionary,
        ::com::sun::star::frame::XStorable
    >
{

    ::cppu::OInterfaceContainerHelper                           aDicEvtListeners;
    ::com::sun::star::uno::Sequence<
        ::com::sun::star::uno::Reference<
            ::com::sun::star::linguistic2::XDictionaryEntry > > aEntries;
    ::rtl::OUString                                             aDicName;
    ::rtl::OUString                                             aMainURL;
    ::com::sun::star::linguistic2::DictionaryType               eDicType;
    INT16                                                       nCount;
    INT16                                                       nLanguage;
    INT16                                                       nDicVersion;
    BOOL                                                        bNeedEntries;
    BOOL                                                        bIsModified;
    BOOL                                                        bIsActive;
    BOOL                                                        bIsReadonly;

    // disallow copy-constructor and assignment-operator for now
    DictionaryNeo(const DictionaryNeo &);
    DictionaryNeo & operator = (const DictionaryNeo &);

    void                    launchEvent(INT16 nEvent,
        ::com::sun::star::uno::Reference<
            ::com::sun::star::linguistic2::XDictionaryEntry > xEntry);

    ULONG                   loadEntries(const ::rtl::OUString &rMainURL);
    ULONG                   saveEntries(const ::rtl::OUString &rMainURL);
    int                     cmpDicEntry(const ::rtl::OUString &rWord1,
                                        const ::rtl::OUString &rWord2,
                                        BOOL bSimilarOnly = FALSE);
    BOOL                    seekEntry(const ::rtl::OUString &rWord, INT32 *pPos,
                                        BOOL bSimilarOnly = FALSE);
    BOOL                    isSorted();

    BOOL                    addEntry_Impl(const ::com::sun::star::uno::Reference<
        ::com::sun::star::linguistic2::XDictionaryEntry > xDicEntry,
                                          BOOL bIsLoadEntries = FALSE);

public:
    DictionaryNeo();
    DictionaryNeo(const ::rtl::OUString &rName, INT16 nLang,
                    ::com::sun::star::linguistic2::DictionaryType eType,
                      const ::rtl::OUString &rMainURL);
    virtual ~DictionaryNeo();

    // XNamed
    virtual ::rtl::OUString SAL_CALL
        getName()
            throw(::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL
        setName( const ::rtl::OUString& aName )
            throw(::com::sun::star::uno::RuntimeException);

    // XDictionary1 (same as XDictionary but for sal_Int16 as language)
    // only the different ones are listed
    virtual sal_Int16 SAL_CALL
        getLanguage()
            throw(::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL
        setLanguage( sal_Int16 nLang )
            throw(::com::sun::star::uno::RuntimeException);

    // XDictionary
    virtual ::com::sun::star::linguistic2::DictionaryType SAL_CALL
        getDictionaryType()
            throw(::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL
        setActive( sal_Bool bActivate )
            throw(::com::sun::star::uno::RuntimeException);
    virtual sal_Bool SAL_CALL
        isActive()
            throw(::com::sun::star::uno::RuntimeException);
    virtual sal_Int16 SAL_CALL
        getCount()
            throw(::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::lang::Locale SAL_CALL
        getLocale()
            throw(::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL
        setLocale( const ::com::sun::star::lang::Locale& aLocale )
            throw(::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::uno::Reference<
            ::com::sun::star::linguistic2::XDictionaryEntry > SAL_CALL
        getEntry( const ::rtl::OUString& aWord )
            throw(::com::sun::star::uno::RuntimeException);
    virtual sal_Bool SAL_CALL
        addEntry( const ::com::sun::star::uno::Reference<
                ::com::sun::star::linguistic2::XDictionaryEntry >& xDicEntry )
            throw(::com::sun::star::uno::RuntimeException);
    virtual sal_Bool SAL_CALL
        add( const ::rtl::OUString& aWord, sal_Bool bIsNegative,
                const ::rtl::OUString& aRplcText )
            throw(::com::sun::star::uno::RuntimeException);
    virtual sal_Bool SAL_CALL
        remove( const ::rtl::OUString& aWord )
            throw(::com::sun::star::uno::RuntimeException);
    virtual sal_Bool SAL_CALL
        isFull()
            throw(::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::uno::Sequence<
            ::com::sun::star::uno::Reference<
                ::com::sun::star::linguistic2::XDictionaryEntry > > SAL_CALL
        getEntries()
            throw(::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL
        clear()
            throw(::com::sun::star::uno::RuntimeException);
    virtual sal_Bool SAL_CALL
        addDictionaryEventListener( const ::com::sun::star::uno::Reference<
                ::com::sun::star::linguistic2::XDictionaryEventListener >& xListener )
            throw(::com::sun::star::uno::RuntimeException);
    virtual sal_Bool SAL_CALL
        removeDictionaryEventListener( const ::com::sun::star::uno::Reference<
                ::com::sun::star::linguistic2::XDictionaryEventListener >& xListener )
            throw(::com::sun::star::uno::RuntimeException);

    // XStorable
    virtual sal_Bool SAL_CALL
        hasLocation()
            throw(::com::sun::star::uno::RuntimeException);
    virtual ::rtl::OUString SAL_CALL
        getLocation()
            throw(::com::sun::star::uno::RuntimeException);
    virtual sal_Bool SAL_CALL
        isReadonly()
            throw(::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL
        store()
            throw(::com::sun::star::io::IOException,
                  ::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL
        storeAsURL( const ::rtl::OUString& aURL,
                const ::com::sun::star::uno::Sequence<
                    ::com::sun::star::beans::PropertyValue >& aArgs )
            throw(::com::sun::star::io::IOException,
                  ::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL
        storeToURL( const ::rtl::OUString& aURL,
                const ::com::sun::star::uno::Sequence<
                    ::com::sun::star::beans::PropertyValue >& aArgs )
            throw(::com::sun::star::io::IOException,
                  ::com::sun::star::uno::RuntimeException);
};

///////////////////////////////////////////////////////////////////////////

class DicEntry :
    public cppu::WeakImplHelper1
    <
        ::com::sun::star::linguistic2::XDictionaryEntry
    >
{
    ::rtl::OUString aDicWord,       // including hyphen positions represented by "="
                    aReplacement;   // including hyphen positions represented by "="
    BOOL            bIsNegativ;

    // disallow copy-constructor and assignment-operator for now
    DicEntry(const DicEntry &);
    DicEntry & operator = (const DicEntry &);

    void            splitDicFileWord(const ::rtl::OUString &rDicFileWord,
                                     ::rtl::OUString &rDicWord,
                                     ::rtl::OUString &rReplacement);

public:
    DicEntry();
    DicEntry(const ::rtl::OUString &rDicFileWord, BOOL bIsNegativ);
    DicEntry(const ::rtl::OUString &rDicWord, BOOL bIsNegativ,
             const ::rtl::OUString &rRplcText);
    virtual ~DicEntry();

    // XDictionaryEntry
    virtual ::rtl::OUString SAL_CALL
        getDictionaryWord() throw(::com::sun::star::uno::RuntimeException);
    virtual sal_Bool SAL_CALL
        isNegative() throw(::com::sun::star::uno::RuntimeException);
    virtual ::rtl::OUString SAL_CALL
        getReplacementText() throw(::com::sun::star::uno::RuntimeException);
};

///////////////////////////////////////////////////////////////////////////

#endif

<commit_msg>INTEGRATION: CWS tl18 (1.5.24); FILE MERGED 2006/03/08 10:13:39 tl 1.5.24.1: #i60698# introducing new, optional tagged file format for user-dictionaries<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: dicimp.hxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: rt $ $Date: 2006-05-05 08:10:18 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _LINGUISTIC_DICIMP_HXX_
#define _LINGUISTIC_DICIMP_HXX_

#include <com/sun/star/linguistic2/XDictionary1.hpp>
#include <com/sun/star/linguistic2/XDictionary.hpp>
#include <com/sun/star/frame/XStorable.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>

#include <uno/lbnames.h>            // CPPU_CURRENT_LANGUAGE_BINDING_NAME macro, which specify the environment type
#include <cppuhelper/implbase3.hxx> // helper for implementations
#include <cppuhelper/implbase1.hxx> // helper for implementations

#ifndef _CPPUHELPER_INTERFACECONTAINER_H_
#include <cppuhelper/interfacecontainer.h>
#endif

#ifndef _STRING_HXX
#include <tools/string.hxx>
#endif

#ifndef _STREAM_HXX
#include <tools/stream.hxx>
#endif

#include "misc.hxx"

///////////////////////////////////////////////////////////////////////////

#define DIC_MAX_ENTRIES     2000

int             ReadDicVersion( SvStream *pStream, USHORT &nLng, BOOL &bNeg );
const String    GetDicExtension();

///////////////////////////////////////////////////////////////////////////

class DictionaryNeo :
    public ::cppu::WeakImplHelper3
    <
        ::com::sun::star::linguistic2::XDictionary1,
        ::com::sun::star::linguistic2::XDictionary,
        ::com::sun::star::frame::XStorable
    >
{

    ::cppu::OInterfaceContainerHelper                           aDicEvtListeners;
    ::com::sun::star::uno::Sequence<
        ::com::sun::star::uno::Reference<
            ::com::sun::star::linguistic2::XDictionaryEntry > > aEntries;
    ::rtl::OUString                                             aDicName;
    ::rtl::OUString                                             aMainURL;
    ::com::sun::star::linguistic2::DictionaryType               eDicType;
    INT16                                                       nCount;
    INT16                                                       nLanguage;
    INT16                                                       nDicVersion;
    BOOL                                                        bNeedEntries;
    BOOL                                                        bIsModified;
    BOOL                                                        bIsActive;
    BOOL                                                        bIsReadonly;

    // disallow copy-constructor and assignment-operator for now
    DictionaryNeo(const DictionaryNeo &);
    DictionaryNeo & operator = (const DictionaryNeo &);

    void                    launchEvent(INT16 nEvent,
        ::com::sun::star::uno::Reference<
            ::com::sun::star::linguistic2::XDictionaryEntry > xEntry);

    ULONG                   loadEntries(const ::rtl::OUString &rMainURL);
    ULONG                   saveEntries(const ::rtl::OUString &rMainURL);
    int                     cmpDicEntry(const ::rtl::OUString &rWord1,
                                        const ::rtl::OUString &rWord2,
                                        BOOL bSimilarOnly = FALSE);
    BOOL                    seekEntry(const ::rtl::OUString &rWord, INT32 *pPos,
                                        BOOL bSimilarOnly = FALSE);
    BOOL                    isSorted();

    BOOL                    addEntry_Impl(const ::com::sun::star::uno::Reference<
        ::com::sun::star::linguistic2::XDictionaryEntry > xDicEntry,
                                          BOOL bIsLoadEntries = FALSE);

public:
    DictionaryNeo();
    DictionaryNeo(const ::rtl::OUString &rName, INT16 nLang,
                    ::com::sun::star::linguistic2::DictionaryType eType,
                      const ::rtl::OUString &rMainURL);
    virtual ~DictionaryNeo();

    // XNamed
    virtual ::rtl::OUString SAL_CALL
        getName()
            throw(::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL
        setName( const ::rtl::OUString& aName )
            throw(::com::sun::star::uno::RuntimeException);

    // XDictionary1 (same as XDictionary but for sal_Int16 as language)
    // only the different ones are listed
    virtual sal_Int16 SAL_CALL
        getLanguage()
            throw(::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL
        setLanguage( sal_Int16 nLang )
            throw(::com::sun::star::uno::RuntimeException);

    // XDictionary
    virtual ::com::sun::star::linguistic2::DictionaryType SAL_CALL
        getDictionaryType()
            throw(::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL
        setActive( sal_Bool bActivate )
            throw(::com::sun::star::uno::RuntimeException);
    virtual sal_Bool SAL_CALL
        isActive()
            throw(::com::sun::star::uno::RuntimeException);
    virtual sal_Int16 SAL_CALL
        getCount()
            throw(::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::lang::Locale SAL_CALL
        getLocale()
            throw(::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL
        setLocale( const ::com::sun::star::lang::Locale& aLocale )
            throw(::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::uno::Reference<
            ::com::sun::star::linguistic2::XDictionaryEntry > SAL_CALL
        getEntry( const ::rtl::OUString& aWord )
            throw(::com::sun::star::uno::RuntimeException);
    virtual sal_Bool SAL_CALL
        addEntry( const ::com::sun::star::uno::Reference<
                ::com::sun::star::linguistic2::XDictionaryEntry >& xDicEntry )
            throw(::com::sun::star::uno::RuntimeException);
    virtual sal_Bool SAL_CALL
        add( const ::rtl::OUString& aWord, sal_Bool bIsNegative,
                const ::rtl::OUString& aRplcText )
            throw(::com::sun::star::uno::RuntimeException);
    virtual sal_Bool SAL_CALL
        remove( const ::rtl::OUString& aWord )
            throw(::com::sun::star::uno::RuntimeException);
    virtual sal_Bool SAL_CALL
        isFull()
            throw(::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::uno::Sequence<
            ::com::sun::star::uno::Reference<
                ::com::sun::star::linguistic2::XDictionaryEntry > > SAL_CALL
        getEntries()
            throw(::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL
        clear()
            throw(::com::sun::star::uno::RuntimeException);
    virtual sal_Bool SAL_CALL
        addDictionaryEventListener( const ::com::sun::star::uno::Reference<
                ::com::sun::star::linguistic2::XDictionaryEventListener >& xListener )
            throw(::com::sun::star::uno::RuntimeException);
    virtual sal_Bool SAL_CALL
        removeDictionaryEventListener( const ::com::sun::star::uno::Reference<
                ::com::sun::star::linguistic2::XDictionaryEventListener >& xListener )
            throw(::com::sun::star::uno::RuntimeException);

    // XStorable
    virtual sal_Bool SAL_CALL
        hasLocation()
            throw(::com::sun::star::uno::RuntimeException);
    virtual ::rtl::OUString SAL_CALL
        getLocation()
            throw(::com::sun::star::uno::RuntimeException);
    virtual sal_Bool SAL_CALL
        isReadonly()
            throw(::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL
        store()
            throw(::com::sun::star::io::IOException,
                  ::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL
        storeAsURL( const ::rtl::OUString& aURL,
                const ::com::sun::star::uno::Sequence<
                    ::com::sun::star::beans::PropertyValue >& aArgs )
            throw(::com::sun::star::io::IOException,
                  ::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL
        storeToURL( const ::rtl::OUString& aURL,
                const ::com::sun::star::uno::Sequence<
                    ::com::sun::star::beans::PropertyValue >& aArgs )
            throw(::com::sun::star::io::IOException,
                  ::com::sun::star::uno::RuntimeException);
};

///////////////////////////////////////////////////////////////////////////

class DicEntry :
    public cppu::WeakImplHelper1
    <
        ::com::sun::star::linguistic2::XDictionaryEntry
    >
{
    ::rtl::OUString aDicWord,       // including hyphen positions represented by "="
                    aReplacement;   // including hyphen positions represented by "="
    BOOL            bIsNegativ;

    // disallow copy-constructor and assignment-operator for now
    DicEntry(const DicEntry &);
    DicEntry & operator = (const DicEntry &);

    void            splitDicFileWord(const ::rtl::OUString &rDicFileWord,
                                     ::rtl::OUString &rDicWord,
                                     ::rtl::OUString &rReplacement);

public:
    DicEntry();
    DicEntry(const ::rtl::OUString &rDicFileWord, BOOL bIsNegativ);
    DicEntry(const ::rtl::OUString &rDicWord, BOOL bIsNegativ,
             const ::rtl::OUString &rRplcText);
    virtual ~DicEntry();

    // XDictionaryEntry
    virtual ::rtl::OUString SAL_CALL
        getDictionaryWord() throw(::com::sun::star::uno::RuntimeException);
    virtual sal_Bool SAL_CALL
        isNegative() throw(::com::sun::star::uno::RuntimeException);
    virtual ::rtl::OUString SAL_CALL
        getReplacementText() throw(::com::sun::star::uno::RuntimeException);
};

///////////////////////////////////////////////////////////////////////////

#endif

<|endoftext|>


<commit_before><commit_msg>Added warning when zphot falls out of confidence interval<commit_after><|endoftext|>


<commit_before><commit_msg>Update fmcalc.cpp<commit_after><|endoftext|>


<commit_before><commit_msg>Fix check for existing serial connection before flashing fw.<commit_after><|endoftext|>