From e5ec0ef6a256b96a758815ef861526f53d1ad7a5 Mon Sep 17 00:00:00 2001 From: zautrix Date: Fri, 01 Apr 2005 14:41:00 +0000 Subject: fix --- diff --git a/korganizer/koagendaview.cpp b/korganizer/koagendaview.cpp index 2996acb..218396d 100644 --- a/korganizer/koagendaview.cpp +++ b/korganizer/koagendaview.cpp @@ -81,8 +81,10 @@ using namespace KOrg; TimeLabels::TimeLabels(int rows,QWidget *parent,const char *name,WFlags f) : QScrollView(parent,name,f) { + myPix.resize( 1, 1 ); mRows = rows; + mRedrawNeeded = true; setMinimumHeight( 20 ); mCellHeight = KOPrefs::instance()->mHourSize*4; @@ -116,73 +118,80 @@ void TimeLabels::drawContents(QPainter *p,int cx, int cy, int cw, int ch) // now, for a workaround... // these two assignments fix the weird redraw bug - cx = contentsX() + 2; - cw = contentsWidth() - 2; - // end of workaround - - int cell = ((int)(cy/mCellHeight)); - int y = cell * mCellHeight; - QFontMetrics fm = fontMetrics(); - QString hour; - QString suffix; - int tW = fm.width("24:00i"); - int timeHeight = fm.height(); - //timeHeight -= (timeHeight/4-2); - int borderWidth = 0; - QFont nFont = p->font(); + if ( mRedrawNeeded ) { + cx = contentsX() + 2; + cw = contentsWidth() - 2; + // end of workaround + + int cell = ((int)(cy/mCellHeight)); + int y = cell * mCellHeight; + QFontMetrics fm = fontMetrics(); + QString hour; + QString suffix; + int tW = fm.width("24:00i"); + int timeHeight = fm.height(); + //timeHeight -= (timeHeight/4-2); + int borderWidth = 0; + QFont nFont = p->font(); - if (!KGlobal::locale()->use12Clock()) - suffix = "00"; - else - borderWidth = 0; - if ( timeHeight > mCellHeight ) { - timeHeight = mCellHeight-1; - int pointS = nFont.pointSize(); - while ( pointS > 4 ) { - nFont.setPointSize( pointS ); + if (!KGlobal::locale()->use12Clock()) + suffix = "00"; + else + borderWidth = 0; + if ( timeHeight > mCellHeight ) { + timeHeight = mCellHeight-1; + int pointS = nFont.pointSize(); + while ( pointS > 4 ) { + nFont.setPointSize( pointS ); + fm = QFontMetrics( nFont ); + if ( fm.height() < mCellHeight ) + break; + -- pointS; + } fm = QFontMetrics( nFont ); - if ( fm.height() < mCellHeight ) - break; - -- pointS; - } - fm = QFontMetrics( nFont ); - borderWidth = 4; - timeHeight = fm.height(); - } - timeHeight -= (timeHeight/4-2); - QFont sFont = nFont; - sFont.setPointSize( sFont.pointSize()/2+2 ); - QFontMetrics fmS( sFont ); - int sHei = fmS.height(); - sHei -= (sHei/4-2); - int startW = this->width() - frameWidth(); - while (y < cy + ch) { - p->drawLine(cx,y,cx+tW,y); - hour.setNum(cell); - - // handle 24h and am/pm time formats - if (KGlobal::locale()->use12Clock()) { - if (cell > 11) suffix = "pm"; - else - suffix = "am"; - if (cell == 0) hour.setNum(12); - if (cell > 12) hour.setNum(cell - 12); + borderWidth = 4; + timeHeight = fm.height(); } + timeHeight -= (timeHeight/4-2); + QFont sFont = nFont; + sFont.setPointSize( sFont.pointSize()/2+2 ); + QFontMetrics fmS( sFont ); + int sHei = fmS.height(); + sHei -= (sHei/4-2); + int startW = this->width() - frameWidth(); + while (y < cy + ch) { + p->drawLine(cx,y,cx+tW,y); + hour.setNum(cell); + + // handle 24h and am/pm time formats + if (KGlobal::locale()->use12Clock()) { + if (cell > 11) suffix = "pm"; + else + suffix = "am"; + if (cell == 0) hour.setNum(12); + if (cell > 12) hour.setNum(cell - 12); + } - // center and draw the time label - int timeWidth = fm.width(hour+"i"); - int tw2 = fm.width(suffix); - int offset = startW - timeWidth - tw2 ; - p->setFont( nFont ); - p->drawText(cx - borderWidth + offset, y+ timeHeight, hour); - p->setFont( sFont ); - offset = startW - tw2-1; - p->drawText(cx - borderWidth + offset, y+ sHei, suffix); - - // increment indices - y += mCellHeight; - cell++; + // center and draw the time label + int timeWidth = fm.width(hour+"i"); + int tw2 = fm.width(suffix); + int offset = startW - timeWidth - tw2 ; + p->setFont( nFont ); + p->drawText(cx - borderWidth + offset, y+ timeHeight, hour); + p->setFont( sFont ); + offset = startW - tw2-1; + p->drawText(cx - borderWidth + offset, y+ sHei, suffix); + + // increment indices + y += mCellHeight; + cell++; + } + } else { + //qDebug("NO redraw "); } + // double buffer not yet implemented + //bitBlt (this, 0, 0, &myPix, 0 ,0,width(), height() ,CopyROP); + //mRedrawNeeded = false; } /** @@ -196,6 +205,7 @@ int TimeLabels::minimumWidth() const /** updates widget's internal state */ void TimeLabels::updateConfig() { + mRedrawNeeded = true; // set the font // config->setGroup("Fonts"); // QFont font = config->readFontEntry("TimeBar Font"); diff --git a/korganizer/koagendaview.h b/korganizer/koagendaview.h index 6dc81c6..30c9b05 100644 --- a/korganizer/koagendaview.h +++ b/korganizer/koagendaview.h @@ -101,6 +101,8 @@ class TimeLabels : public QScrollView { void drawContents(QPainter *p,int cx, int cy, int cw, int ch); private: + QPixmap myPix; + bool mRedrawNeeded; int mMiniWidth; int mMouseDownY; QString mOrgCap; diff --git a/korganizer/kodaymatrix.cpp b/korganizer/kodaymatrix.cpp index d543aaf..dfc6af7 100644 --- a/korganizer/kodaymatrix.cpp +++ b/korganizer/kodaymatrix.cpp @@ -110,6 +110,7 @@ KODayMatrix::KODayMatrix(QWidget *parent, Calendar* calendar, QDate date, const QFrame(parent, name) #endif { + mRedrawNeeded = true; mKODaymatrixWhatsThis = new KODaymatrixWhatsThis(this); mPendingUpdateBeforeRepaint = false; mouseDown = false; @@ -386,6 +387,7 @@ void KODayMatrix::updateViewTimed() mHolidays[i] = QString::null; } } + mRedrawNeeded = true; if ( ! mPendingUpdateBeforeRepaint ) repaint(false); } @@ -420,6 +422,7 @@ void KODayMatrix::updateView(QDate actdate) startdate = actdate; mDayChanged = true; recalculateToday(); + mRedrawNeeded = true; } //qDebug("restart Timer %d vis: %d", mDayChanged, isVisible() ); if ( !isVisible() ) { @@ -428,7 +431,7 @@ void KODayMatrix::updateView(QDate actdate) #ifdef DESKTOP_VERSION //mRepaintTimer->start( 100 ); //updateViewTimed(); - mUpdateTimer->start( 20 ); + mUpdateTimer->start( 50 ); #else mRepaintTimer->start( 350 ); mUpdateTimer->start( 1200 ); @@ -678,258 +681,264 @@ void KODayMatrix::paintEvent(QPaintEvent * pevent) } if ( myPix.width() != width() || myPix.height()!=height() ) { myPix.resize(size() ); + mRedrawNeeded = true; } - QPainter p(&myPix); - p.setFont(font()); + if ( mRedrawNeeded ) { + //qDebug("REDRAW "); + QPainter p(&myPix); + p.setFont(font()); - int dheight = daysize.height(); - int dwidth = daysize.width(); - int row,col; - int selw, selh; - int xyOff = frameWidth(); - int colModulo = (width()-2) % 7; - int rowModulo = (height()-2) % 6; - //qDebug("col %d row %d ",colModulo,rowModulo ); + + int dheight = daysize.height(); + int dwidth = daysize.width(); + int row,col; + int selw, selh; + int xyOff = frameWidth(); + int colModulo = (width()-2) % 7; + int rowModulo = (height()-2) % 6; + //qDebug("col %d row %d ",colModulo,rowModulo ); - bool isRTL = KOGlobals::self()->reverseLayout(); - - // draw background and topleft frame - p.fillRect(0,0,width(),height(), mDefaultBackColor); - p.setPen(mDefaultTextColor); - p.drawRect(0, 0, width(), height()); - int mSelStartT = mSelStart; - int mSelEndT = mSelEnd; - if ( mSelEndT >= NUMDAYS ) - mSelEndT = NUMDAYS-1; - // draw selected days with highlighted background color - if (mSelStart != NOSELECTION) { - bool skip = false; - if ( ! mouseDown ) { - int mo = days[20].month(); - //qDebug("-- %d %d ", mSelStartT, mSelEndT); - //qDebug("%d %d %d - d %d", mo, days[mSelStartT].month() , days[mSelEndT].month(), days[mSelEndT].day() ); - int startMo = days[mSelStartT].month(); - int endMo = days[mSelEndT].month(); - if ( startMo == 12 && mo == 1 && endMo <= 2 ) - startMo = 1; - if ( endMo == 1 && mo == 12 ) - endMo = 12; - if ( mo == 12 && startMo == 1 ) - startMo = 13; - if ( (startMo > mo || endMo < mo) ) { - skip = true; - } else { - if ( days[mSelStartT].month() != mo ) { - int add = days[mSelStartT].daysInMonth ()-days[mSelStartT].day(); - mSelStartT += add +1; - } - if ( days[mSelEndT].month() != mo ) { - int sub = days[mSelEndT].day(); - mSelEndT -= sub ; - } - } - } - //qDebug("SKIP %d ", skip); - if ( ! skip ) { - row = mSelStartT/7; - col = mSelStartT -row*7; - QColor selcol = KOPrefs::instance()->mHighlightColor; - int addCol = 0; - int addRow = 0; - int addRow2 = 0; - int addCol2 = 0; - if (row == mSelEndT/7) { - if ( rowModulo ) { - if ( row >= 6 - rowModulo ) - addRow = row - 5 + rowModulo; - } - if ( colModulo ) { - int colt1 = mSelEndT%7; - //qDebug("colt1 %d ", colt1 ); - if ( colt1 >= 7 - colModulo ) - addCol = colt1 - 7 + colModulo+1; - int colt = mSelStartT%7; - if ( colt >= 7 - colModulo ) - addCol2 = colt - 7 + colModulo; - addCol -= addCol2; - //qDebug("COL %d %d %d %d ",col , colt1 ,addCol ,addCol2 ); - } - // Single row selection - if ( row == 0) - addRow = 1; - p.fillRect(isRTL ? (7 - (mSelEndT-mSelStartT+1) - col)*dwidth : col*dwidth+1+addCol2, - row*dheight+addRow, (mSelEndT-mSelStartT+1)*dwidth+addCol, dheight+1, selcol); - } else { - // draw first row to the right - if ( colModulo ) { - if ( col >= 7 - colModulo ) - addCol2 = col - 7 + colModulo; - } - if ( rowModulo ) { - if ( row >= 6 - rowModulo ) - addRow = row - 5 + rowModulo; - } - if ( row == 0) - addRow = 1; - int drawWid = width()-(col*dwidth+1+addCol2)-1; - p.fillRect(isRTL ? 0 : col*dwidth+1+addCol2, row*dheight+addRow, drawWid, - dheight+1, selcol); - // draw full block till last line - selh = mSelEndT/7-row; - addRow = 0; - if ( rowModulo ) { - if ( mSelEndT/7 >= 6 - rowModulo ) - addRow = mSelEndT/7 - 5 + rowModulo; - } - if (selh > 1) { - p.fillRect(1, (row+1)*dheight, 7*dwidth+colModulo, (selh-1)*dheight+addRow,selcol); - } - // draw last block from left to mSelEndT - selw = mSelEndT-7*(mSelEndT/7)+1; - //qDebug("esl %d ",selw ); - int add = 0; - if ( colModulo ) { - add = 7 - colModulo; - if ( selw > add ) - add = selw - add; - else - add = 0; - } - //qDebug("add %d ", add); - p.fillRect(isRTL ? (7-selw)*dwidth : 1, (row+selh)*dheight+addRow, - selw*dwidth+add, dheight+1, selcol); - } - } - } + bool isRTL = KOGlobals::self()->reverseLayout(); + + // draw background and topleft frame + p.fillRect(0,0,width(),height(), mDefaultBackColor); + p.setPen(mDefaultTextColor); + p.drawRect(0, 0, width(), height()); + int mSelStartT = mSelStart; + int mSelEndT = mSelEnd; + if ( mSelEndT >= NUMDAYS ) + mSelEndT = NUMDAYS-1; + // draw selected days with highlighted background color + if (mSelStart != NOSELECTION) { + bool skip = false; + if ( ! mouseDown ) { + int mo = days[20].month(); + //qDebug("-- %d %d ", mSelStartT, mSelEndT); + //qDebug("%d %d %d - d %d", mo, days[mSelStartT].month() , days[mSelEndT].month(), days[mSelEndT].day() ); + int startMo = days[mSelStartT].month(); + int endMo = days[mSelEndT].month(); + if ( startMo == 12 && mo == 1 && endMo <= 2 ) + startMo = 1; + if ( endMo == 1 && mo == 12 ) + endMo = 12; + if ( mo == 12 && startMo == 1 ) + startMo = 13; + if ( (startMo > mo || endMo < mo) ) { + skip = true; + } else { + if ( days[mSelStartT].month() != mo ) { + int add = days[mSelStartT].daysInMonth ()-days[mSelStartT].day(); + mSelStartT += add +1; + } + if ( days[mSelEndT].month() != mo ) { + int sub = days[mSelEndT].day(); + mSelEndT -= sub ; + } + } + } + //qDebug("SKIP %d ", skip); + if ( ! skip ) { + row = mSelStartT/7; + col = mSelStartT -row*7; + QColor selcol = KOPrefs::instance()->mHighlightColor; + int addCol = 0; + int addRow = 0; + int addRow2 = 0; + int addCol2 = 0; + if (row == mSelEndT/7) { + if ( rowModulo ) { + if ( row >= 6 - rowModulo ) + addRow = row - 5 + rowModulo; + } + if ( colModulo ) { + int colt1 = mSelEndT%7; + //qDebug("colt1 %d ", colt1 ); + if ( colt1 >= 7 - colModulo ) + addCol = colt1 - 7 + colModulo+1; + int colt = mSelStartT%7; + if ( colt >= 7 - colModulo ) + addCol2 = colt - 7 + colModulo; + addCol -= addCol2; + //qDebug("COL %d %d %d %d ",col , colt1 ,addCol ,addCol2 ); + } + // Single row selection + if ( row == 0) + addRow = 1; + p.fillRect(isRTL ? (7 - (mSelEndT-mSelStartT+1) - col)*dwidth : col*dwidth+1+addCol2, + row*dheight+addRow, (mSelEndT-mSelStartT+1)*dwidth+addCol, dheight+1, selcol); + } else { + // draw first row to the right + if ( colModulo ) { + if ( col >= 7 - colModulo ) + addCol2 = col - 7 + colModulo; + } + if ( rowModulo ) { + if ( row >= 6 - rowModulo ) + addRow = row - 5 + rowModulo; + } + if ( row == 0) + addRow = 1; + int drawWid = width()-(col*dwidth+1+addCol2)-1; + p.fillRect(isRTL ? 0 : col*dwidth+1+addCol2, row*dheight+addRow, drawWid, + dheight+1, selcol); + // draw full block till last line + selh = mSelEndT/7-row; + addRow = 0; + if ( rowModulo ) { + if ( mSelEndT/7 >= 6 - rowModulo ) + addRow = mSelEndT/7 - 5 + rowModulo; + } + if (selh > 1) { + p.fillRect(1, (row+1)*dheight, 7*dwidth+colModulo, (selh-1)*dheight+addRow,selcol); + } + // draw last block from left to mSelEndT + selw = mSelEndT-7*(mSelEndT/7)+1; + //qDebug("esl %d ",selw ); + int add = 0; + if ( colModulo ) { + add = 7 - colModulo; + if ( selw > add ) + add = selw - add; + else + add = 0; + } + //qDebug("add %d ", add); + p.fillRect(isRTL ? (7-selw)*dwidth : 1, (row+selh)*dheight+addRow, + selw*dwidth+add, dheight+1, selcol); + } + } + } - // iterate over all days in the matrix and draw the day label in appropriate colors - QColor actcol = mDefaultTextColorShaded; - p.setPen(actcol); - QPen tmppen; - for(int i = 0; i < NUMDAYS; i++) { - row = i/7; - col = isRTL ? 6-(i-row*7) : i-row*7; - - // if it is the first day of a month switch color from normal to shaded and vice versa - if ( KOGlobals::self()->calendarSystem()->day( days[i] ) == 1) { - if (actcol == mDefaultTextColorShaded) { - actcol = mDefaultTextColor; - } else { - actcol = mDefaultTextColorShaded; - } - p.setPen(actcol); - } - if (actcol == mDefaultTextColorShaded) { - if ( ! mouseDown ) { - continue; - } - } - //Reset pen color after selected days block - if (i == mSelEndT+1) { - p.setPen(actcol); - } + // iterate over all days in the matrix and draw the day label in appropriate colors + QColor actcol = mDefaultTextColorShaded; + p.setPen(actcol); + QPen tmppen; + for(int i = 0; i < NUMDAYS; i++) { + row = i/7; + col = isRTL ? 6-(i-row*7) : i-row*7; + + // if it is the first day of a month switch color from normal to shaded and vice versa + if ( KOGlobals::self()->calendarSystem()->day( days[i] ) == 1) { + if (actcol == mDefaultTextColorShaded) { + actcol = mDefaultTextColor; + } else { + actcol = mDefaultTextColorShaded; + } + p.setPen(actcol); + } + if (actcol == mDefaultTextColorShaded) { + if ( ! mouseDown ) { + continue; + } + } + //Reset pen color after selected days block + if (i == mSelEndT+1) { + p.setPen(actcol); + } - // if today then draw rectangle around day - if (today == i) { - tmppen = p.pen(); - QPen mTodayPen(p.pen()); - if ( daysize.width() < 20 ) - mTodayPen.setWidth(1); - else - mTodayPen.setWidth(mTodayMarginWidth); - //draw red rectangle for holidays - if (!mHolidays[i].isNull()) { - if (actcol == mDefaultTextColor) { - mTodayPen.setColor(KOPrefs::instance()->mHolidayColor); - } else { - mTodayPen.setColor(mHolidayColorShaded); - } - } - //draw gray rectangle for today if in selection - if (i >= mSelStartT && i <= mSelEndT) { - QColor grey("grey"); - mTodayPen.setColor(grey); - } - p.setPen(mTodayPen); - - - int addCol = 0; - int addRow = 0; - if (rowModulo) { - if ( row >= 6 - rowModulo ) - addRow = row - 5 + rowModulo; - } - if ( colModulo ) { - if ( col >= 7 - colModulo ) - addCol = col - 6 + colModulo-1; - } + // if today then draw rectangle around day + if (today == i) { + tmppen = p.pen(); + QPen mTodayPen(p.pen()); + if ( daysize.width() < 20 ) + mTodayPen.setWidth(1); + else + mTodayPen.setWidth(mTodayMarginWidth); + //draw red rectangle for holidays + if (!mHolidays[i].isNull()) { + if (actcol == mDefaultTextColor) { + mTodayPen.setColor(KOPrefs::instance()->mHolidayColor); + } else { + mTodayPen.setColor(mHolidayColorShaded); + } + } + //draw gray rectangle for today if in selection + if (i >= mSelStartT && i <= mSelEndT) { + QColor grey("grey"); + mTodayPen.setColor(grey); + } + p.setPen(mTodayPen); + + + int addCol = 0; + int addRow = 0; + if (rowModulo) { + if ( row >= 6 - rowModulo ) + addRow = row - 5 + rowModulo; + } + if ( colModulo ) { + if ( col >= 7 - colModulo ) + addCol = col - 6 + colModulo-1; + } - addCol += 1; - p.drawRect(col*dwidth+addCol, row*dheight+addRow, dwidth, dheight+1); - p.setPen(tmppen); - } + addCol += 1; + p.drawRect(col*dwidth+addCol, row*dheight+addRow, dwidth, dheight+1); + p.setPen(tmppen); + } - // if any events are on that day then draw it using a bold font - if ( eDays.testBit(i) ) { - QFont myFont = font(); - myFont.setBold(true); - p.setFont(myFont); - } + // if any events are on that day then draw it using a bold font + if ( eDays.testBit(i) ) { + QFont myFont = font(); + myFont.setBold(true); + p.setFont(myFont); + } - // if it is a holiday then use the default holiday color - if ( !mHolidays[i].isNull()) { - if ( bDays.testBit(i) ) { - if ( hDays.testBit(i) ) - p.setPen(QColor(Qt::green)); - else - p.setPen(QColor(Qt::green).dark()); - } else { - if (actcol == mDefaultTextColor ) { - p.setPen(KOPrefs::instance()->mHolidayColor); - } else { - p.setPen(mHolidayColorShaded); - } - } - } + // if it is a holiday then use the default holiday color + if ( !mHolidays[i].isNull()) { + if ( bDays.testBit(i) ) { + if ( hDays.testBit(i) ) + p.setPen(QColor(Qt::green)); + else + p.setPen(QColor(Qt::green).dark()); + } else { + if (actcol == mDefaultTextColor ) { + p.setPen(KOPrefs::instance()->mHolidayColor); + } else { + p.setPen(mHolidayColorShaded); + } + } + } - // draw selected days with special color - // DO NOT specially highlight holidays in selection ! - if (i >= mSelStartT && i <= mSelEndT) { - ;//p.setPen(mSelectedDaysColor); - } + // draw selected days with special color + // DO NOT specially highlight holidays in selection ! + if (i >= mSelStartT && i <= mSelEndT) { + ;//p.setPen(mSelectedDaysColor); + } - int addCol = 0; - int addRow = 0; - if ( colModulo ) { - if ( col >= 7 - colModulo ) - addCol = col - 7 + colModulo; - } - if ( rowModulo ) { - if ( row >= 6 - rowModulo ) - addRow = row - 5 + rowModulo; - } - //qDebug("add %d %d -- %d %d ", col, addCol, row, addRow); - ++addCol;//++addCol; - if ( row == 0) - addRow = 1; - p.drawText(col*dwidth+addCol, row*dheight+addRow, dwidth, dheight, - Qt::AlignHCenter | Qt::AlignVCenter, daylbls[i]); - - // reset color to actual color - if (!mHolidays[i].isNull()) { - p.setPen(actcol); - } - // reset bold font to plain font - if ( eDays.testBit(i)) { - QFont myFont = font(); - myFont.setBold(false); - p.setFont(myFont); - } - } - int off = 0;//xyOff; - bitBlt (this, off, off, &myPix, 0 ,0,width(), height() ,CopyROP); - //qDebug("ffffffffff %d ", off); + int addCol = 0; + int addRow = 0; + if ( colModulo ) { + if ( col >= 7 - colModulo ) + addCol = col - 7 + colModulo; + } + if ( rowModulo ) { + if ( row >= 6 - rowModulo ) + addRow = row - 5 + rowModulo; + } + //qDebug("add %d %d -- %d %d ", col, addCol, row, addRow); + ++addCol;//++addCol; + if ( row == 0) + addRow = 1; + p.drawText(col*dwidth+addCol, row*dheight+addRow, dwidth, dheight, + Qt::AlignHCenter | Qt::AlignVCenter, daylbls[i]); + + // reset color to actual color + if (!mHolidays[i].isNull()) { + p.setPen(actcol); + } + // reset bold font to plain font + if ( eDays.testBit(i)) { + QFont myFont = font(); + myFont.setBold(false); + p.setFont(myFont); + } + } + } else { + //qDebug("NO redraw "); + } + bitBlt (this, 0, 0, &myPix, 0 ,0,width(), height() ,CopyROP); + mRedrawNeeded = false; } // ---------------------------------------------------------------------------- diff --git a/korganizer/kodaymatrix.h b/korganizer/kodaymatrix.h index 38a7f92..731117c 100644 --- a/korganizer/kodaymatrix.h +++ b/korganizer/kodaymatrix.h @@ -227,6 +227,7 @@ protected: void resizeEvent(QResizeEvent *); private: + bool mRedrawNeeded; KODaymatrixWhatsThis* mKODaymatrixWhatsThis; bool mouseDown; QBitArray bDays; -- cgit v0.9.0.2