mirror of
https://bitbucket.org/smil3y/kde-playground.git
synced 2025-02-24 10:52:52 +00:00
788 lines
22 KiB
C++
788 lines
22 KiB
C++
/*
|
|
Copyright (c) 2008 Bruno Virlet <bruno.virlet@gmail.com>
|
|
|
|
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.
|
|
|
|
As a special exception, permission is given to link this program
|
|
with any edition of Qt, and distribute the resulting executable,
|
|
without including the source code for Qt in the source distribution.
|
|
*/
|
|
|
|
#include "monthscene.h"
|
|
#include "monthgraphicsitems.h"
|
|
#include "monthitem.h"
|
|
#include "monthview.h"
|
|
#include "prefs.h"
|
|
|
|
#include <calendarsupport/utils.h>
|
|
|
|
#include <KCalendarSystem>
|
|
#include <KIconLoader>
|
|
|
|
#include <QGraphicsSceneMouseEvent>
|
|
#include <QResizeEvent>
|
|
|
|
static const int AUTO_REPEAT_DELAY = 600;
|
|
|
|
using namespace EventViews;
|
|
|
|
MonthScene::MonthScene( MonthView *parent )
|
|
: QGraphicsScene( parent ),
|
|
mMonthView( parent ),
|
|
mInitialized( false ),
|
|
mClickedItem( 0 ),
|
|
mActionItem( 0 ),
|
|
mActionInitiated( false ),
|
|
mSelectedItem( 0 ),
|
|
mStartCell( 0 ),
|
|
mPreviousCell( 0 ),
|
|
mActionType( None ),
|
|
mStartHeight( 0 ),
|
|
mCurrentIndicator( 0 )
|
|
{
|
|
mBirthdayPixmap = SmallIcon( QLatin1String("view-calendar-birthday") );
|
|
mAnniversaryPixmap = SmallIcon( QLatin1String("view-calendar-wedding-anniversary") );
|
|
mAlarmPixmap = SmallIcon( QLatin1String("appointment-reminder" ));
|
|
mRecurPixmap = SmallIcon( QLatin1String("appointment-recurring") );
|
|
mReadonlyPixmap = SmallIcon( QLatin1String("object-locked") );
|
|
mReplyPixmap = SmallIcon( QLatin1String("mail-reply-sender") );
|
|
mHolidayPixmap = SmallIcon( QLatin1String("view-calendar-holiday") );
|
|
|
|
setSceneRect( 0, 0, parent->width(), parent->height() );
|
|
}
|
|
|
|
MonthScene::~MonthScene()
|
|
{
|
|
qDeleteAll( mMonthCellMap );
|
|
qDeleteAll( mManagerList );
|
|
}
|
|
|
|
MonthCell *MonthScene::selectedCell() const
|
|
{
|
|
return mMonthCellMap.value( mSelectedCellDate );
|
|
}
|
|
|
|
MonthCell *MonthScene::previousCell() const
|
|
{
|
|
return mPreviousCell;
|
|
}
|
|
|
|
int MonthScene::getRightSpan( const QDate &date ) const
|
|
{
|
|
MonthCell *cell = mMonthCellMap.value( date );
|
|
if ( !cell ) {
|
|
return 0;
|
|
}
|
|
|
|
return 7 - cell->x() - 1;
|
|
}
|
|
|
|
int MonthScene::getLeftSpan( const QDate &date ) const
|
|
{
|
|
MonthCell *cell = mMonthCellMap.value( date );
|
|
if ( !cell ) {
|
|
return 0;
|
|
}
|
|
|
|
return cell->x();
|
|
}
|
|
|
|
int MonthScene::maxRowCount()
|
|
{
|
|
return ( rowHeight() - MonthCell::topMargin() ) / itemHeightIncludingSpacing();
|
|
}
|
|
|
|
int MonthScene::itemHeightIncludingSpacing()
|
|
{
|
|
return MonthCell::topMargin() + 2;
|
|
}
|
|
|
|
int MonthScene::itemHeight()
|
|
{
|
|
return MonthCell::topMargin();
|
|
}
|
|
|
|
MonthCell *MonthScene::firstCellForMonthItem( MonthItem *manager )
|
|
{
|
|
for ( QDate d = manager->startDate(); d <= manager->endDate(); d = d.addDays( 1 ) ) {
|
|
MonthCell *monthCell = mMonthCellMap.value( d );
|
|
if ( monthCell ) {
|
|
return monthCell;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void MonthScene::updateGeometry()
|
|
{
|
|
foreach ( MonthItem *manager, mManagerList ) {
|
|
manager->updateGeometry();
|
|
}
|
|
}
|
|
|
|
int MonthScene::availableWidth() const
|
|
{
|
|
return static_cast<int> ( sceneRect().width() );
|
|
}
|
|
|
|
int MonthScene::availableHeight() const
|
|
{
|
|
return static_cast<int> ( sceneRect().height() - headerHeight() );
|
|
}
|
|
|
|
int MonthScene::columnWidth() const
|
|
{
|
|
return static_cast<int> ( ( availableWidth() - 1 ) / 7. );
|
|
}
|
|
|
|
int MonthScene::rowHeight() const
|
|
{
|
|
return static_cast<int> ( ( availableHeight() - 1 ) / 6. );
|
|
}
|
|
|
|
int MonthScene::headerHeight() const
|
|
{
|
|
return 50;
|
|
}
|
|
|
|
int MonthScene::cellVerticalPos( const MonthCell *cell ) const
|
|
{
|
|
return headerHeight() + cell->y() * rowHeight();
|
|
}
|
|
|
|
int MonthScene::cellHorizontalPos( const MonthCell *cell ) const
|
|
{
|
|
return cell->x() * columnWidth();
|
|
}
|
|
|
|
int MonthScene::sceneYToMonthGridY( int yScene )
|
|
{
|
|
return yScene - headerHeight();
|
|
}
|
|
|
|
int MonthScene::sceneXToMonthGridX( int xScene )
|
|
{
|
|
return xScene;
|
|
}
|
|
|
|
void MonthGraphicsView::drawBackground( QPainter *p, const QRectF & rect )
|
|
{
|
|
Q_ASSERT( mScene );
|
|
PrefsPtr prefs = mScene->monthView()->preferences();
|
|
p->setFont( prefs->monthViewFont() );
|
|
p->fillRect( rect, palette().color( QPalette::Base ) );
|
|
|
|
/*
|
|
Headers
|
|
*/
|
|
QFont font = prefs->monthViewFont();
|
|
font.setBold( true );
|
|
font.setPointSize( 15 );
|
|
p->setFont( font );
|
|
const int dayLabelsHeight = 20;
|
|
const KCalendarSystem *calSys = KGlobal::locale()->calendar();
|
|
p->drawText( QRect( 0, 0, // top right
|
|
static_cast<int> ( mScene->sceneRect().width() ),
|
|
static_cast<int> ( mScene->headerHeight() - dayLabelsHeight ) ),
|
|
Qt::AlignCenter,
|
|
i18nc( "monthname year", "%1 %2",
|
|
calSys->monthName( mMonthView->averageDate() ),
|
|
calSys->formatDate( mMonthView->averageDate(),
|
|
KLocale::Year, KLocale::LongNumber ) ) );
|
|
|
|
font.setPixelSize( dayLabelsHeight - 10 );
|
|
p->setFont( font );
|
|
|
|
const QDate start = mMonthView->actualStartDateTime().date();
|
|
const QDate end = mMonthView->actualEndDateTime().date();
|
|
|
|
for ( QDate d = start;
|
|
d <= start.addDays( 6 ); d = d.addDays( 1 ) ) {
|
|
MonthCell *cell = mScene->mMonthCellMap.value( d );
|
|
|
|
if ( !cell ) {
|
|
// This means drawBackground() is being called before reloadIncidences(). Can happen with some
|
|
// themes. Bug #190191
|
|
return;
|
|
}
|
|
|
|
p->drawText( QRect( mScene->cellHorizontalPos( cell ),
|
|
mScene->cellVerticalPos( cell ) - 15,
|
|
mScene->columnWidth(),
|
|
15 ),
|
|
Qt::AlignCenter,
|
|
calSys->weekDayName( d, KCalendarSystem::LongDayName ) );
|
|
}
|
|
|
|
/*
|
|
Month grid
|
|
*/
|
|
int columnWidth = mScene->columnWidth();
|
|
int rowHeight = mScene->rowHeight();
|
|
|
|
const QList<QDate> workDays = CalendarSupport::workDays( mMonthView->actualStartDateTime().date(),
|
|
mMonthView->actualEndDateTime().date() );
|
|
|
|
for ( QDate d = start; d <= end; d = d.addDays( 1 ) ) {
|
|
if ( !mScene->mMonthCellMap.contains( d ) ) {
|
|
// This means drawBackground() is being called before reloadIncidences(). Can happen with some
|
|
// themes. Bug #190191
|
|
return;
|
|
}
|
|
|
|
MonthCell *cell = mScene->mMonthCellMap[ d ];
|
|
|
|
QColor color;
|
|
if ( workDays.contains( d ) ) {
|
|
color = mMonthView->preferences()->monthGridWorkHoursBackgroundColor();
|
|
} else {
|
|
color = mMonthView->preferences()->monthGridBackgroundColor();
|
|
}
|
|
if ( cell == mScene->selectedCell() ) {
|
|
color = color.dark( 115 );
|
|
}
|
|
if ( cell->date() == QDate::currentDate() ) {
|
|
color = color.dark( 140 );
|
|
}
|
|
|
|
// Draw cell
|
|
p->setPen( mMonthView->preferences()->monthGridBackgroundColor().dark( 150 ) );
|
|
p->setBrush( color );
|
|
p->drawRect( QRect( mScene->cellHorizontalPos( cell ), mScene->cellVerticalPos( cell ),
|
|
columnWidth, rowHeight ) );
|
|
|
|
if ( mMonthView->isBusyDay( d ) ) {
|
|
QColor busyColor = mMonthView->preferences()->viewBgBusyColor();
|
|
busyColor.setAlpha( EventViews::BUSY_BACKGROUND_ALPHA );
|
|
p->setBrush( busyColor );
|
|
p->drawRect( QRect( mScene->cellHorizontalPos( cell ), mScene->cellVerticalPos( cell ),
|
|
columnWidth, rowHeight ) );
|
|
}
|
|
|
|
// Draw cell header
|
|
int cellHeaderX = mScene->cellHorizontalPos( cell ) + 1;
|
|
int cellHeaderY = mScene->cellVerticalPos( cell ) + 1;
|
|
int cellHeaderWidth = columnWidth - 2;
|
|
int cellHeaderHeight = cell->topMargin() - 2;
|
|
QLinearGradient bgGradient( QPointF( cellHeaderX, cellHeaderY ),
|
|
QPointF( cellHeaderX + cellHeaderWidth,
|
|
cellHeaderY + cellHeaderHeight ) );
|
|
bgGradient.setColorAt( 0, color.dark( 105 ) );
|
|
bgGradient.setColorAt( 0.7, color.dark( 105 ) );
|
|
bgGradient.setColorAt( 1, color );
|
|
p->setBrush( bgGradient );
|
|
|
|
p->setPen( Qt::NoPen );
|
|
p->drawRect( QRect( cellHeaderX, cellHeaderY,
|
|
cellHeaderWidth, cellHeaderHeight ) );
|
|
}
|
|
|
|
font = mMonthView->preferences()->monthViewFont();
|
|
font.setPixelSize( MonthCell::topMargin() - 4 );
|
|
|
|
p->setFont( font );
|
|
|
|
QPen oldPen = mMonthView->preferences()->monthGridBackgroundColor().dark( 150 );
|
|
|
|
// Draw dates
|
|
for ( QDate d = mMonthView->actualStartDateTime().date();
|
|
d <= mMonthView->actualEndDateTime().date(); d = d.addDays( 1 ) ) {
|
|
MonthCell *cell = mScene->mMonthCellMap.value( d );
|
|
|
|
QFont font = p->font();
|
|
if ( cell->date() == QDate::currentDate() ) {
|
|
font.setBold( true );
|
|
} else {
|
|
font.setBold( false );
|
|
}
|
|
p->setFont( font );
|
|
|
|
if ( d.month() == mMonthView->currentMonth() ) {
|
|
p->setPen( QPalette::Text );
|
|
} else {
|
|
p->setPen( oldPen );
|
|
}
|
|
|
|
/*
|
|
Draw arrows if all items won't fit
|
|
*/
|
|
|
|
// Up arrow if first item is above cell top
|
|
if ( mScene->startHeight() != 0 && cell->hasEventBelow( mScene->startHeight() ) ) {
|
|
cell->upArrow()->setPos(
|
|
mScene->cellHorizontalPos( cell ) + columnWidth / 2,
|
|
mScene->cellVerticalPos( cell ) + cell->upArrow()->boundingRect().height() / 2 + 2 );
|
|
cell->upArrow()->show();
|
|
} else {
|
|
cell->upArrow()->hide();
|
|
}
|
|
|
|
// Down arrow if last item is below cell bottom
|
|
if ( !mScene->lastItemFit( cell ) ) {
|
|
cell->downArrow()->setPos(
|
|
mScene->cellHorizontalPos( cell ) + columnWidth / 2,
|
|
mScene->cellVerticalPos( cell ) + rowHeight -
|
|
cell->downArrow()->boundingRect().height() / 2 - 2 );
|
|
cell->downArrow()->show();
|
|
} else {
|
|
cell->downArrow()->hide();
|
|
}
|
|
|
|
const KCalendarSystem *calSys = KGlobal::locale()->calendar();
|
|
|
|
QString dayText;
|
|
// Prepend month name if d is the first or last day of month
|
|
if ( calSys->day( d ) == 1 || // d is the first day of month
|
|
calSys->day( d.addDays( 1 ) ) == 1 ) { // d is the last day of month
|
|
dayText = i18nc( "'Month day' for month view cells", "%1 %2",
|
|
calSys->monthName( d, KCalendarSystem::ShortName ),
|
|
calSys->day( d ) );
|
|
} else {
|
|
dayText = QString::number( calSys->day( d ) );
|
|
}
|
|
|
|
p->drawText( QRect( mScene->cellHorizontalPos( cell ), // top right
|
|
mScene->cellVerticalPos( cell ), // of the cell
|
|
mScene->columnWidth() - 2,
|
|
cell->topMargin() ),
|
|
Qt::AlignRight,
|
|
dayText );
|
|
}
|
|
|
|
// ...
|
|
}
|
|
|
|
void MonthScene::resetAll()
|
|
{
|
|
qDeleteAll( mMonthCellMap );
|
|
mMonthCellMap.clear();
|
|
|
|
qDeleteAll( mManagerList );
|
|
mManagerList.clear();
|
|
|
|
mSelectedItem = 0;
|
|
mActionItem = 0;
|
|
mClickedItem = 0;
|
|
}
|
|
|
|
Akonadi::IncidenceChanger *MonthScene::incidenceChanger() const
|
|
{
|
|
return mMonthView->changer();
|
|
}
|
|
|
|
QDate MonthScene::firstDateOnRow( int row ) const
|
|
{
|
|
return mMonthView->actualStartDateTime().date().addDays( 7 * row );
|
|
}
|
|
|
|
bool MonthScene::lastItemFit( MonthCell *cell )
|
|
{
|
|
if ( cell->firstFreeSpace() > maxRowCount() + startHeight() ) {
|
|
return false;
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
int MonthScene::totalHeight()
|
|
{
|
|
int max = 0;
|
|
for ( QDate d = mMonthView->actualStartDateTime().date();
|
|
d <= mMonthView->actualEndDateTime().date(); d = d.addDays( 1 ) ) {
|
|
int c = mMonthCellMap[ d ]->firstFreeSpace();
|
|
if ( c > max ) {
|
|
max = c;
|
|
}
|
|
}
|
|
|
|
return max;
|
|
}
|
|
|
|
void MonthScene::wheelEvent( QGraphicsSceneWheelEvent *event )
|
|
{
|
|
Q_UNUSED( event ); // until we figure out what to do in here
|
|
|
|
/* int numDegrees = -event->delta() / 8;
|
|
int numSteps = numDegrees / 15;
|
|
|
|
if ( startHeight() + numSteps < 0 ) {
|
|
numSteps = -startHeight();
|
|
}
|
|
|
|
int cellHeight = 0;
|
|
|
|
MonthCell *currentCell = getCellFromPos( event->scenePos() );
|
|
if ( currentCell ) {
|
|
cellHeight = currentCell->firstFreeSpace();
|
|
}
|
|
if ( cellHeight == 0 ) {
|
|
// no items in this cell, there's no point to scroll
|
|
return;
|
|
}
|
|
|
|
int newHeight;
|
|
int maxStartHeight = qMax( 0, cellHeight - maxRowCount() );
|
|
if ( numSteps > 0 && startHeight() + numSteps >= maxStartHeight ) {
|
|
newHeight = maxStartHeight;
|
|
} else {
|
|
newHeight = startHeight() + numSteps;
|
|
}
|
|
|
|
if ( newHeight == startHeight() ) {
|
|
return;
|
|
}
|
|
|
|
setStartHeight( newHeight );
|
|
|
|
foreach ( MonthItem *manager, mManagerList ) {
|
|
manager->updateGeometry();
|
|
}
|
|
|
|
invalidate( QRectF(), BackgroundLayer );
|
|
|
|
event->accept();
|
|
*/
|
|
}
|
|
|
|
void MonthScene::scrollCellsDown()
|
|
{
|
|
int newHeight = startHeight() + 1;
|
|
setStartHeight( newHeight );
|
|
|
|
foreach ( MonthItem *manager, mManagerList ) {
|
|
manager->updateGeometry();
|
|
}
|
|
|
|
invalidate( QRectF(), BackgroundLayer );
|
|
}
|
|
|
|
void MonthScene::scrollCellsUp()
|
|
{
|
|
int newHeight = startHeight() - 1;
|
|
setStartHeight( newHeight );
|
|
|
|
foreach ( MonthItem *manager, mManagerList ) {
|
|
manager->updateGeometry();
|
|
}
|
|
|
|
invalidate( QRectF(), BackgroundLayer );
|
|
}
|
|
|
|
void MonthScene::clickOnScrollIndicator( ScrollIndicator *scrollItem )
|
|
{
|
|
if ( scrollItem->direction() == ScrollIndicator::UpArrow ) {
|
|
scrollCellsUp();
|
|
} else if ( scrollItem->direction() == ScrollIndicator::DownArrow ) {
|
|
scrollCellsDown();
|
|
}
|
|
}
|
|
|
|
void MonthScene::mouseDoubleClickEvent ( QGraphicsSceneMouseEvent *mouseEvent )
|
|
{
|
|
QPointF pos = mouseEvent->scenePos();
|
|
repeatTimer.stop();
|
|
MonthGraphicsItem *iItem = dynamic_cast<MonthGraphicsItem*>( itemAt( pos ) );
|
|
if ( iItem ) {
|
|
if ( iItem->monthItem() ) {
|
|
IncidenceMonthItem *tmp = qobject_cast<IncidenceMonthItem *>( iItem->monthItem() );
|
|
if ( tmp ) {
|
|
selectItem( iItem->monthItem() );
|
|
mMonthView->defaultAction( tmp->akonadiItem() );
|
|
|
|
mouseEvent->accept();
|
|
}
|
|
}
|
|
} else {
|
|
emit newEventSignal();
|
|
}
|
|
}
|
|
|
|
void MonthScene::mouseMoveEvent ( QGraphicsSceneMouseEvent *mouseEvent )
|
|
{
|
|
QPointF pos = mouseEvent->scenePos();
|
|
|
|
MonthGraphicsView *view = static_cast<MonthGraphicsView*>( views().first() );
|
|
|
|
// Change cursor depending on the part of the item it hovers to inform
|
|
// the user that he can resize the item.
|
|
if ( mActionType == None ) {
|
|
MonthGraphicsItem *iItem = dynamic_cast<MonthGraphicsItem*>( itemAt( pos ) );
|
|
if ( iItem ) {
|
|
if ( iItem->monthItem()->isResizable() &&
|
|
iItem->isBeginItem() && iItem->mapFromScene( pos ).x() <= 10 ) {
|
|
view->setActionCursor( Resize );
|
|
} else if ( iItem->monthItem()->isResizable() &&
|
|
iItem->isEndItem() &&
|
|
iItem->mapFromScene( pos ).x() >= iItem->boundingRect().width() - 10 ) {
|
|
view->setActionCursor( Resize );
|
|
} else {
|
|
view->setActionCursor( None );
|
|
}
|
|
} else {
|
|
view->setActionCursor( None );
|
|
}
|
|
mouseEvent->accept();
|
|
return;
|
|
}
|
|
|
|
// If an item was selected during the click, we maybe have an item to move !
|
|
if ( mActionItem ) {
|
|
MonthCell *currentCell = getCellFromPos( pos );
|
|
|
|
// Initiate action if not already done
|
|
if ( !mActionInitiated && mActionType != None ) {
|
|
if ( mActionType == Move ) {
|
|
mActionItem->beginMove();
|
|
} else if ( mActionType == Resize ) {
|
|
mActionItem->beginResize();
|
|
}
|
|
mActionInitiated = true;
|
|
}
|
|
view->setActionCursor( mActionType );
|
|
|
|
// Move or resize action
|
|
if ( currentCell && currentCell != mPreviousCell ) {
|
|
|
|
bool ok = true;
|
|
if ( mActionType == Move ) {
|
|
mActionItem->moveBy( mPreviousCell->date().daysTo( currentCell->date() ) );
|
|
} else if ( mActionType == Resize ) {
|
|
ok = mActionItem->resizeBy( mPreviousCell->date().daysTo( currentCell->date() ) );
|
|
}
|
|
|
|
if ( ok ) {
|
|
mPreviousCell = currentCell;
|
|
}
|
|
mActionItem->updateGeometry();
|
|
update();
|
|
}
|
|
mouseEvent->accept();
|
|
}
|
|
}
|
|
|
|
void MonthScene::mousePressEvent ( QGraphicsSceneMouseEvent *mouseEvent )
|
|
{
|
|
QPointF pos = mouseEvent->scenePos();
|
|
|
|
mClickedItem = 0;
|
|
mCurrentIndicator = 0;
|
|
|
|
MonthGraphicsItem *iItem = dynamic_cast<MonthGraphicsItem*>( itemAt( pos ) );
|
|
if ( iItem ) {
|
|
mClickedItem = iItem->monthItem();
|
|
|
|
selectItem( mClickedItem );
|
|
if ( mouseEvent->button() == Qt::RightButton ) {
|
|
IncidenceMonthItem *tmp = qobject_cast<IncidenceMonthItem *>( mClickedItem );
|
|
if ( tmp ) {
|
|
emit showIncidencePopupSignal( tmp->akonadiItem(), tmp->realStartDate() );
|
|
}
|
|
}
|
|
|
|
if ( mouseEvent->button() == Qt::LeftButton ) {
|
|
// Basic initialization for resize and move
|
|
mActionItem = mClickedItem;
|
|
mStartCell = getCellFromPos( pos );
|
|
mPreviousCell = mStartCell;
|
|
mActionInitiated = false;
|
|
|
|
// Move or resize ?
|
|
if ( iItem->monthItem()->isResizable() &&
|
|
iItem->isBeginItem() && iItem->mapFromScene( pos ).x() <= 10 ) {
|
|
mActionType = Resize;
|
|
mResizeType = ResizeLeft;
|
|
} else if ( iItem->monthItem()->isResizable() &&
|
|
iItem->isEndItem() &&
|
|
iItem->mapFromScene( pos ).x() >= iItem->boundingRect().width() - 10 ) {
|
|
mActionType = Resize;
|
|
mResizeType = ResizeRight;
|
|
} else if ( iItem->monthItem()->isMoveable() ) {
|
|
mActionType = Move;
|
|
}
|
|
}
|
|
mouseEvent->accept();
|
|
} else if ( ScrollIndicator *scrollItem = dynamic_cast<ScrollIndicator*>( itemAt( pos ) ) ) {
|
|
clickOnScrollIndicator( scrollItem );
|
|
mCurrentIndicator = scrollItem;
|
|
repeatTimer.start( AUTO_REPEAT_DELAY, this );
|
|
} else {
|
|
// unselect items when clicking somewhere else
|
|
selectItem( 0 );
|
|
|
|
MonthCell *cell = getCellFromPos( pos );
|
|
if ( cell ) {
|
|
mSelectedCellDate = cell->date();
|
|
update();
|
|
if ( mouseEvent->button() == Qt::RightButton ) {
|
|
emit showNewEventPopupSignal();
|
|
}
|
|
mouseEvent->accept();
|
|
}
|
|
}
|
|
}
|
|
|
|
void MonthScene::timerEvent( QTimerEvent *e )
|
|
{
|
|
if ( e->timerId() == repeatTimer.timerId() ) {
|
|
if ( mCurrentIndicator->isVisible() ) {
|
|
clickOnScrollIndicator( mCurrentIndicator );
|
|
repeatTimer.start( AUTO_REPEAT_DELAY, this );
|
|
} else {
|
|
mCurrentIndicator = 0;
|
|
repeatTimer.stop();
|
|
}
|
|
}
|
|
}
|
|
|
|
void MonthScene::mouseReleaseEvent ( QGraphicsSceneMouseEvent *mouseEvent )
|
|
{
|
|
QPointF pos = mouseEvent->scenePos();
|
|
|
|
static_cast<MonthGraphicsView*>( views().first() )->setActionCursor( None );
|
|
|
|
repeatTimer.stop();
|
|
mCurrentIndicator = 0;
|
|
|
|
if ( mActionItem ) {
|
|
MonthCell *currentCell = getCellFromPos( pos );
|
|
|
|
const bool somethingChanged = currentCell && currentCell != mStartCell;
|
|
|
|
if ( somethingChanged ) { // We want to act if a move really happened
|
|
if ( mActionType == Resize ) {
|
|
mActionItem->endResize();
|
|
} else if ( mActionType == Move ) {
|
|
mActionItem->endMove();
|
|
}
|
|
}
|
|
|
|
mActionItem = 0;
|
|
mActionType = None;
|
|
mStartCell = 0;
|
|
|
|
mouseEvent->accept();
|
|
}
|
|
}
|
|
|
|
// returns true if the point is in the monthgrid (allows to avoid selecting a cell when
|
|
// a click is outside the month grid
|
|
bool MonthScene::isInMonthGrid( int x, int y ) const
|
|
{
|
|
return x >= 0 && y >= 0 && x <= availableWidth() && y <= availableHeight();
|
|
}
|
|
|
|
// The function converts the coordinates to the month grid coordinates to
|
|
// be able to locate the cell.
|
|
MonthCell *MonthScene::getCellFromPos( const QPointF &pos )
|
|
{
|
|
int y = sceneYToMonthGridY( static_cast<int> ( pos.y() ) );
|
|
int x = sceneXToMonthGridX( static_cast<int> ( pos.x() ) );
|
|
if ( !isInMonthGrid( x, y ) ) {
|
|
return 0;
|
|
}
|
|
int id = ( int )( y / rowHeight() ) * 7 + ( int )( x / columnWidth() );
|
|
|
|
return mMonthCellMap.value( mMonthView->actualStartDateTime().date().addDays( id ) );
|
|
}
|
|
|
|
void MonthScene::selectItem( MonthItem *item )
|
|
{
|
|
/*
|
|
if ( mSelectedItem == item ) {
|
|
return;
|
|
}
|
|
|
|
I commented the above code so it's possible to selected a selected item.
|
|
korg-mobile needs that, otherwise clicking on a selected item wont bring the editor up.
|
|
Another solution would be to have two signals: incidenceSelected() and incidenceClicked()
|
|
*/
|
|
|
|
IncidenceMonthItem *tmp = qobject_cast<IncidenceMonthItem*>( item );
|
|
|
|
if ( !tmp ) {
|
|
mSelectedItem = 0;
|
|
emit incidenceSelected( Akonadi::Item(), QDate() );
|
|
return;
|
|
}
|
|
|
|
mSelectedItem = item;
|
|
Q_ASSERT( CalendarSupport::hasIncidence( tmp->akonadiItem() ) );
|
|
|
|
if ( mMonthView->selectedIncidenceDates().isEmpty() ) {
|
|
emit incidenceSelected( tmp->akonadiItem(), QDate() );
|
|
} else {
|
|
emit incidenceSelected( tmp->akonadiItem(), mMonthView->selectedIncidenceDates().first() );
|
|
}
|
|
update();
|
|
}
|
|
|
|
void MonthScene::removeIncidence( const QString &uid )
|
|
{
|
|
foreach ( MonthItem *manager, mManagerList ) {
|
|
IncidenceMonthItem *imi = qobject_cast<IncidenceMonthItem*>( manager );
|
|
if ( !imi )
|
|
continue;
|
|
|
|
KCalCore::Incidence::Ptr incidence = imi->incidence();
|
|
if ( !incidence )
|
|
continue;
|
|
if ( incidence->uid() == uid ) {
|
|
foreach ( MonthGraphicsItem *gitem, imi->monthGraphicsItems() ) {
|
|
removeItem( gitem );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------
|
|
MonthGraphicsView::MonthGraphicsView( MonthView *parent )
|
|
: QGraphicsView( parent ), mMonthView( parent )
|
|
{
|
|
setMouseTracking( true );
|
|
}
|
|
|
|
void MonthGraphicsView::setActionCursor( MonthScene::ActionType actionType )
|
|
{
|
|
switch ( actionType ) {
|
|
case MonthScene::Move:
|
|
#ifndef QT_NO_CURSOR
|
|
setCursor( Qt::ArrowCursor );
|
|
#endif
|
|
break;
|
|
case MonthScene::Resize:
|
|
#ifndef QT_NO_CURSOR
|
|
setCursor( Qt::SizeHorCursor );
|
|
#endif
|
|
break;
|
|
#ifndef QT_NO_CURSOR
|
|
default:
|
|
setCursor( Qt::ArrowCursor );
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void MonthGraphicsView::setScene( MonthScene *scene )
|
|
{
|
|
mScene = scene;
|
|
QGraphicsView::setScene( scene );
|
|
}
|
|
|
|
void MonthGraphicsView::resizeEvent( QResizeEvent *event )
|
|
{
|
|
mScene->setSceneRect( 0, 0, event->size().width(), event->size().height() );
|
|
mScene->updateGeometry();
|
|
}
|
|
|