[svn-upgrade] new version confclerk (0.5.4) upstream/0.5.4
authorgregor herrmann <gregoa@debian.org>
Wed, 14 Sep 2011 18:47:19 +0000 (18:47 -0000)
committergregor herrmann <gregoa@debian.org>
Wed, 14 Sep 2011 18:47:19 +0000 (18:47 -0000)
21 files changed:
ChangeLog
NEWS
README
data/confclerk.1
data/confclerk.png
data/confclerk.pod
src/global.pri
src/gui/conferenceeditor.cpp
src/gui/daynavigatorwidget.cpp
src/gui/daynavigatorwidget.h
src/gui/mainwindow.cpp
src/gui/mainwindow.ui
src/gui/tabcontainer.cpp
src/gui/tabcontainer.ui
src/mvc/delegate.cpp
src/mvc/delegate.h
src/mvc/eventmodel.cpp
src/mvc/eventmodel.h
src/mvc/treeview.cpp
src/orm/ormrecord.h
src/sql/sqlengine.cpp

index 8d6fb43df1e658f90fc8e7c9975cfd210d7d51f0..214de1cfec7904e4c62501194f40dbe93ed77284 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,59 @@
+2011-09-14  gregoa
+
+       * NEWS: Add date to NEWS before release.
+
+2011-09-12  gregoa
+
+       * NEWS: Add NEWS items for upcoming 0.5.4 release.
+       * NEWS: Add dates to all releases in NEWS.
+       * src/gui/daynavigatorwidget.cpp: Day navigator widget: setDates()
+         - change logic of setting mCurDate: if it's outside the
+         conference range, set it to mStartDate (and not to mEndDate when
+         it's "greater") -- when going to an earlier conference, starting
+         on the last day doesn't really make sense - update() the widget
+         after changing dates. this might be a bit expensive but it ensure
+         that the displayed date is what we want, and since there are many
+         day navigator widgets there's probably no single other place
+         
+         Hopefully closes #36.
+       * src/gui/mainwindow.cpp: Replace some tabs with the usual spaces.
+
+2011-09-06  philipp
+
+       * src/gui/mainwindow.ui: Assigned confclerk icon to main window.
+       * src/gui/conferenceeditor.cpp: Now the progress bar is shown
+         immediately after clicking the refresh conference button. Closes
+         ticket #25.
+       * src/gui/daynavigatorwidget.cpp, src/gui/daynavigatorwidget.h,
+         src/gui/tabcontainer.cpp, src/mvc/treeview.cpp: Fixed ticket #26
+         (empty tabs after some actions).
+
+2011-09-06  stefan
+
+       * src/gui/mainwindow.cpp, src/sql/sqlengine.cpp: Fixed ticket #20
+
+2011-09-06  philipp
+
+       * src/orm/ormrecord.h: Removed one comment and fixed typos.
+
+2011-09-06  gregoa
+
+       * README, data/confclerk.pod: Mention frab (FrOSCon penta clone)
+         and Grazer Linuxtage (fixes #33).
+
+2011-08-23  philipp
+
+       * src/mvc/eventmodel.cpp, src/mvc/eventmodel.h: Rewrote code to
+         group events together with gregoa. Closes bug #22.
+       * src/mvc/delegate.cpp: This should close ticket #35 ([maemo]
+         conflict icon overlaps alarm icon).
+       * src/gui/tabcontainer.ui, src/mvc/delegate.cpp,
+         src/mvc/delegate.h: Changed the drawing of events to make use of
+         system colors and styles, at least partially.
+
 2011-08-16  gregoa
 
+       * NEWS, src/global.pri: bump version after release
        * NEWS: Remove "TODO" from NEWS, a.k.a. prepare for release
 
 2011-08-15  gregoa
diff --git a/NEWS b/NEWS
index 00677a0be6a9a45a7b8fc0f6d3caae4bc8f24249..ba960b0b91a1bb0007ab9d3e362719e25d59180c 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,7 +1,16 @@
 This is the NEWS file for ConfClerk. ConfClerk is the successor of
 fosdem-schedule; cf. docs/fosdem-schedule for the historic documentation.
 
-Version 0.5.3
+version 0.5.4, 2011-09-14
+* Change displaying events a bit, use system colours (#13).
+* Fix display of conflict and alarm icon on maemo (#35).
+* Improve logic of grouping events into timeslits (#22).
+* Remove warnings without a database or with an empty one (#20).
+* Import/update: show progressbar immediately (#25).
+* Update dates and text for day navigator widget when switching 
+  conference (#36).
+
+Version 0.5.3, 2011-08-16
 * Add "jump to today" button to date navigator.
   Thanks to Michael Schutte for the patch.
   Fixes: #29
@@ -17,7 +26,7 @@ Version 0.5.2, 2011-07-23
 * Remove event/room records on import to get rid of "old" room names; this
   avoids duplicates when room names change.
 
-Version 0.5.1
+Version 0.5.1, 2011-07-14
 * Improve search function: split search string on whitespace.
 * Various small UI changes, e.g.:
   - cancel button in settings dialogs
@@ -27,7 +36,7 @@ Version 0.5.1
   - remove status bar
   - clean up some dialogs
 
-Version 0.5.0
+Version 0.5.0, 2011-06-29
 * First release of ConfClerk as the fosdem-schedule successor.
 * Continue the multi-conference feature, make sure persons/tracks/rooms are
   handled separately per conference.
diff --git a/README b/README
index 51ade6c8c858a25634b80aa5f435ccee4edb5958..52fb6014a7a45167a50a806702df7a154413c5fc 100644 (file)
--- a/README
+++ b/README
@@ -11,8 +11,8 @@ location, etc.) and enables you to select favorite events and create your own
 schedule.
 
 At the moment ConfClerk is able to import schedules in XML format created by
-the PentaBarf conference management system used by e.g. FOSDEM, DebConf,
-FrOSCon, and the CCC.
+the PentaBarf conference management system (or frab) used by e.g. FOSDEM,
+DebConf, FrOSCon, Grazer Linuxtage, and the CCC.
 
 ConfClerk is targetted at mobile devices like the Nokia N810 and N900 but
 works on any sytem running Qt.
index 1eb4cb75e657fafb2a5dda4439041c4e300d024a..0928b7667bfdfcb0b6876b14c6106fc6d8b86274 100644 (file)
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.23 (Pod::Simple 3.16)
+.\" Automatically generated by Pod::Man 2.23 (Pod::Simple 3.19)
 .\"
 .\" Standard preamble:
 .\" ========================================================================
@@ -62,7 +62,7 @@
 .\" ========================================================================
 .\"
 .IX Title "CONFCLERK 1"
-.TH CONFCLERK 1 "2011-08-15" "Version 0.5.3" "Offlince conference scheduler"
+.TH CONFCLERK 1 "2011-09-07" "Version 0.5.4" "Offlince conference scheduler"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
@@ -81,8 +81,8 @@ location, etc.) and enables you to select favorite events and create your own
 schedule.
 .PP
 At the moment \fBConfClerk\fR is able to import schedules in \s-1XML\s0 format created
-by the PentaBarf conference management system used by e.g. \s-1FOSDEM\s0, DebConf,
-FrOSCon, and the \s-1CCC\s0.
+by the PentaBarf conference management system (or frab) used by e.g. \s-1FOSDEM\s0,
+DebConf, FrOSCon, Grazer Linuxtage, and the \s-1CCC\s0.
 .PP
 ConfClerk is targetted at mobile devices like the Nokia N810 and N900 but
 works on any sytem running Qt.
index 9e681a97ca6232adaa1a1702ed0f93ed8c10f0dc..605f7cd5aaa698f4a6a1b6cb2e4bb1d88947a6fa 100644 (file)
Binary files a/data/confclerk.png and b/data/confclerk.png differ
index 2e5bbd3f566ccf78571654a5348c826ea6fd8d9c..f47e7a741922f500b006192d86ff194e2c614527 100644 (file)
@@ -17,8 +17,8 @@ location, etc.) and enables you to select favorite events and create your own
 schedule.
 
 At the moment B<ConfClerk> is able to import schedules in XML format created
-by the PentaBarf conference management system used by e.g. FOSDEM, DebConf,
-FrOSCon, and the CCC.
+by the PentaBarf conference management system (or frab) used by e.g. FOSDEM,
+DebConf, FrOSCon, Grazer Linuxtage, and the CCC.
 
 ConfClerk is targetted at mobile devices like the Nokia N810 and N900 but
 works on any sytem running Qt.
index 55a06e5495c745777d07df21ce0fe120a8c2a42e..093fe043b9fd865058fea1a7c066d363b335c7d0 100644 (file)
@@ -4,7 +4,7 @@
 # USAGE: include(./global.pri)
 
 # VERSION
-VERSION = 0.5.3
+VERSION = 0.5.4
 DEFINES += VERSION=\\\"$$VERSION\\\"
 
 # Define 'MAEMO' specific CONFIG/DEFINE
index 910a7d09deecd0aa1f7027f87c401e98546fd908..d17bad3adcef95a4e3ab83795319d69ffe366b20 100644 (file)
@@ -130,13 +130,11 @@ void ConferenceEditor::removeClicked()
 
 void ConferenceEditor::changeUrlClicked()
 {
-    if (selected_id < 0) {
-        return;
-    }
-    const Conference& selected = Conference::getById(selected_id);
+    if (selected_id < 0) return;
+    const Conference& selectedConf = Conference::getById(selected_id);
 
     bool ok;
-    QString url = QInputDialog::getText(this, "URL Input", "Enter schedule URL", QLineEdit::Normal, selected.url(), &ok);
+    QString url = QInputDialog::getText(this, "URL Input", "Enter schedule URL", QLineEdit::Normal, selectedConf.url(), &ok);
 
     if (ok) {
         emit changeUrlRequested(selected_id, url);
@@ -145,27 +143,21 @@ void ConferenceEditor::changeUrlClicked()
 
 void ConferenceEditor::refreshClicked()
 {
-    if (selected_id < 0) {
-        return;
-    }
-    const Conference& selected = Conference::getById(selected_id);
+    if (selected_id < 0) return;
+    const Conference& selectedConf = Conference::getById(selected_id);
+    QString url = selectedConf.url();
 
-    QString url = selected.url();
-
-    if (!url.isEmpty()) {
-        emit haveConferenceUrl(url);
-    } else {
+    if (url.isEmpty()) {
         static const QString format("Schedule URL for %1 is not set. Enter the schedule URL:");
         bool ok;
-        QString url = QInputDialog::getText(this, "URL Input", format.arg(selected.title()), QLineEdit::Normal, QString(), &ok);
-
-        if (ok) {
-            // first save it, to remain if fetch fails
-            emit changeUrlRequested(selected_id, url);
-            // then fetch
-            emit haveConferenceUrl(url);
-        }
+        QString url = QInputDialog::getText(this, "URL Input", format.arg(selectedConf.title()), QLineEdit::Normal, QString(), &ok);
+        if (!ok) return;
+        // first save it, to remain if fetch fails
+        emit changeUrlRequested(selected_id, url);
     }
+    // fetch
+    importStarted(); // just to show the progress bar
+    emit haveConferenceUrl(url);
 }
 
 void ConferenceEditor::importStarted()
index 8db754df4df2df7d2923214ec00c84b6ba3622dc..48ca927109a16c8b08ebefae9fbf800faddf3442 100644 (file)
@@ -45,23 +45,14 @@ void DayNavigatorWidget::setDates(const QDate &aStartDate, const QDate &aEndDate
 
     mStartDate = aStartDate;
     mEndDate = aEndDate;
-    mCurDate = aStartDate;
-
-    // QRect rect = mFontMetrics->boundingRect(mCurDate.toString("MMM dd yyyy"));
-
-    if(mStartDate==mEndDate) // only one day conference
-    {
-        prevDayButton->setDisabled(true);
-        nextDayButton->setDisabled(true);
-        emit(dateChanged(mCurDate));
-    }
-    else
-    {
-        // at least 2-days conference
-        prevDayButton->setDisabled(true);
-        nextDayButton->setDisabled(false);
-        emit(dateChanged(mCurDate));
-    }
+    if (!mCurDate.isValid()) mCurDate = mStartDate;
+    // if mCurDate is out of range, set it to mstartDate
+    else if (mCurDate < mStartDate || mCurDate > mEndDate) mCurDate = mStartDate;
+
+    prevDayButton->setDisabled(mCurDate == mStartDate);
+    nextDayButton->setDisabled(mCurDate == mEndDate);
+    emit(dateChanged(mCurDate));
+    this->update();
 }
 
 void DayNavigatorWidget::configureNavigation()
index d4ddcea0ad2da1d06ec1bd9bdf08e9ed20259749..79d71f0748102089dc9b4c37023bf1ace1c2155d 100644 (file)
@@ -77,6 +77,7 @@ class DayNavigatorWidget : public QWidget, private Ui::DayNavigatorWidget
         DayNavigatorWidget(QWidget *aParent = NULL);
         ~DayNavigatorWidget() {}
         void setDates(const QDate &aStartDate, const QDate &aEndDate);
+        QDate curDate() const {return mCurDate;}
     protected:
         void paintEvent(QPaintEvent *);
         void configureNavigation();
index 1e612dac22fc346c9607b560f54f057dbbdc4c74..71c0bee4db3b13de72c30279e7bccd73bad57e26 100644 (file)
@@ -154,19 +154,24 @@ void MainWindow::eventHasChanged(int aEventId, bool aReloadModel)
 
 void MainWindow::useConference(int id)
 {
+    if (id == -1)  // in case no conference is active
+    {
+        unsetConference();
+        return;
+    }
     try {
         Conference::getById(Conference::activeConference()).update("active",0);
         Conference new_active = Conference::getById(id);
         new_active.update("active",1);
 
-       // looks like it does not work at n900
+        // looks like it does not work at n900
         setWindowTitle(new_active.title());
 
         // optimization.
-       // dont run initTabs() here
+        // dont run initTabs() here
         // it takes much CPU, making travelling between conferences in ConferenceEditor longer
         // and is not seen in maemo WM anyway
-       // instead run it explicitly
+        // instead run it explicitly
         // 1. at startup
         // 2. when ConferenceEditor finished
         // dont forget to protect the calls by try-catch!
@@ -178,7 +183,7 @@ void MainWindow::useConference(int id)
         // initTabs();
     } catch (OrmException& e) {
         // cannon set an active conference
-        unsetConference();
+        unsetConference();   // TODO: as no active conference is now correctly managed this should be handled as a fatal error
         return;
     }
 
@@ -187,18 +192,21 @@ void MainWindow::useConference(int id)
 void MainWindow::initTabs()
 {
     int confId = Conference::activeConference();
-    Conference active = Conference::getById(confId);
-    QDate startDate = active.start();
-    QDate endDate = active.end();
-
-    // 'dayNavigator' emits signal 'dateChanged' after setting valid START:END dates
-    dayTabContainer->setDates(startDate, endDate);
-    tracksTabContainer->setDates(startDate, endDate);
-    roomsTabContainer->setDates(startDate, endDate);
-    favsTabContainer->setDates(startDate, endDate);
-    searchTabContainer->setDates(startDate, endDate);
-    searchTabContainer->searchAgainClicked();
-    nowTabContainer->updateTreeView(QDate::currentDate());
+    if (confId != -1)   // only init tabs if a conference is active
+    {
+        Conference active = Conference::getById(confId);
+        QDate startDate = active.start();
+        QDate endDate = active.end();
+
+        // 'dayNavigator' emits signal 'dateChanged' after setting valid START:END dates
+        dayTabContainer->setDates(startDate, endDate);
+        tracksTabContainer->setDates(startDate, endDate);
+        roomsTabContainer->setDates(startDate, endDate);
+        favsTabContainer->setDates(startDate, endDate);
+        searchTabContainer->setDates(startDate, endDate);
+        searchTabContainer->searchAgainClicked();
+        nowTabContainer->updateTreeView(QDate::currentDate());
+    }
 }
 
 void MainWindow::clearTabs()
index 9cd4fde4ffe0180713a04ecf43867db1439da5e4..63b56a48ec74fcf6292130c23164dbc85a91def9 100644 (file)
   <property name="windowTitle">
    <string>ConfClerk</string>
   </property>
+  <property name="windowIcon">
+   <iconset resource="../../data/data.qrc">
+    <normaloff>:/confclerk.svg</normaloff>:/confclerk.svg</iconset>
+  </property>
   <widget class="QWidget" name="centralwidget">
    <layout class="QGridLayout" name="gridLayout">
     <item row="0" column="0">
  </customwidgets>
  <resources>
   <include location="../icons.qrc"/>
+  <include location="../../data/data.qrc"/>
  </resources>
  <connections>
   <connection>
index 357ea35c7a0a7f1fc75e85377b1a241e66581198..c17eff2622f9396314a74a5922c982dbca7e34ec 100644 (file)
@@ -96,13 +96,13 @@ void TabContainer::updateTreeViewModel(int aEventId, bool aReloadModel)
     if(aReloadModel)
     {
         // requires special handling
-        // eg. in case of favourities - some favourities may have changed
+        // eg. in case of favourites - some favourites may have changed
         // and so we need to reload them
         int confId = Conference::activeConference();
         QDate startDate = Conference::getById(confId).start();
         QDate endDate = Conference::getById(confId).end();
         dayNavigator->setDates(startDate, endDate);
-        updateTreeView( Conference::getById(confId).start() );
+        updateTreeView(dayNavigator->curDate());
     }
     else
     {
index 77dcfdedac82d493002ba2d1994e0d8eb0f97a6f..56e6e1069ba7c0865dd9f189764593c67d8a24bc 100644 (file)
@@ -33,6 +33,9 @@
          <verstretch>1</verstretch>
         </sizepolicy>
        </property>
+       <property name="verticalScrollBarPolicy">
+        <enum>Qt::ScrollBarAlwaysOn</enum>
+       </property>
       </widget>
      </item>
     </layout>
index 51cf9e5570eed1960a0b5338d3a8f0f61e87d080..1b7dcb606f11cbd78c81918941d5f63c6387c9e9 100644 (file)
@@ -51,16 +51,13 @@ Delegate::~Delegate()
 
 void Delegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
 {
-    if(!mViewPtr)
+    if (!mViewPtr)
         return;
 
     painter->save();
-    QColor bkgrColor = option.palette.color(QPalette::Background);
-    //QColor bkgrColor = QColor(0xAA,0xAA,0xAA);
-    QColor conflictColor = Qt::yellow;
 
     QColor textColor = option.palette.color(QPalette::Text);
-    QPen borderPen(textColor);
+
     if(hasParent(index))
     {
         // entry horizontal layout:
@@ -69,6 +66,7 @@ void Delegate::paint(QPainter *painter, const QStyleOptionViewItem &option, cons
         // * rest is text, which is 1 line of title with big letters and 2 lines of Presenter and Track
         int aux = option.rect.height() - SPACER - mControls[FavouriteControlOn]->image()->height();
         Event *event = static_cast<Event*>(index.internalPointer());
+
         // font SMALL
         QFont fontSmall = option.font;
         fontSmall.setBold(false);
@@ -77,63 +75,30 @@ void Delegate::paint(QPainter *painter, const QStyleOptionViewItem &option, cons
         // font SMALL bold
         QFont fontSmallB = fontSmall;
         fontSmallB.setBold(true);
-        QFontMetrics fmSmallB(fontSmallB);
 
         // font BIG
         QFont fontBig = option.font;
         fontBig.setBold(false);
         fontBig.setPixelSize(aux*0.33);
         QFontMetrics fmBig(fontBig);
+
         // font BIG bold
         QFont fontBigB = fontBig;
         fontBigB.setBold(true);
         QFontMetrics fmBigB(fontBigB);
 
-        //int spacer = (fmSmall.boundingRect("999").width() < SPACER) ? SPACER : fmSmall.boundingRect("999").width();
-
-        //Time conflicts are colored differently
-        if(event->hasTimeConflict())
-            bkgrColor = conflictColor;
-
-        QLinearGradient itemGradient(option.rect.topLeft(), option.rect.bottomLeft());
-        itemGradient.setColorAt(0.0, bkgrColor);
-        itemGradient.setColorAt(1.0, bkgrColor);
-
-        if(isLast(index))
-        {
-            QPainterPath endPath;
-            endPath.moveTo(option.rect.topLeft());
-            endPath.lineTo(option.rect.bottomLeft()-QPoint(0, RADIUS));
-            endPath.arcTo(option.rect.left(), option.rect.bottom()-2*RADIUS, 2*RADIUS, 2*RADIUS, 180, 90);
-            endPath.lineTo(option.rect.bottomRight()-QPoint(RADIUS, 0));
-            endPath.arcTo(option.rect.right()-2*RADIUS, option.rect.bottom()-2*RADIUS, 2*RADIUS, 2*RADIUS, 270, 90);
-            endPath.lineTo(option.rect.topRight());
-
-            //painter->setBrush( bkgrColor );
-            painter->setBrush(itemGradient);
-            painter->setPen(Qt::NoPen);
-            painter->drawPath(endPath);
-            painter->setPen(borderPen);
-
-            painter->setFont(option.font);
-        }
-        else // middle elements
-        {
-            //painter->setBrush( bkgrColor );
-            painter->setBrush(itemGradient);
+        // background (in case of time conflicts)
+        if(event->hasTimeConflict()) {
+            painter->setBrush(Qt::yellow);
             painter->setPen(Qt::NoPen);
             painter->drawRect(option.rect);
+        }
 
-            painter->setPen(borderPen);
-            /*
-            // vertical lines
-            painter->drawLine(option.rect.topLeft(), option.rect.bottomLeft());
-            painter->drawLine(option.rect.topRight(), option.rect.bottomRight());
-            */
-            // horizontal lines
-            painter->drawLine(option.rect.bottomLeft(), option.rect.bottomRight());
-
-            painter->setFont(option.font);
+        // background (without time conflicts)
+        else {
+            QStyleOption styleOption;
+            styleOption.rect = option.rect;
+            qApp->style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &styleOption, painter, mViewPtr);
         }
 
         // draw Controls
@@ -157,11 +122,13 @@ void Delegate::paint(QPainter *painter, const QStyleOptionViewItem &option, cons
         // it starts just below the image
         // ("position of text" is lower-left angle of the first letter,
         //  so the first line is actually at the same height as the image)
+        painter->setPen(QPen(event->hasTimeConflict() ? Qt::black : textColor));
         QPointF titlePointF(option.rect.x() + SPACER,
                             option.rect.y() + SPACER + mControls[FavouriteControlOn]->image()->height());
         QTime start = event->start().time();
         painter->setFont(fontBig);
         painter->drawText(titlePointF,start.toString("hh:mm") + "-" + start.addSecs(event->duration()).toString("hh:mm") + ", " + event->roomName());
+
         // title
         titlePointF.setY(titlePointF.y()+fmBig.height()-fmBig.descent());
         painter->setFont(fontBigB);
@@ -181,17 +148,30 @@ void Delegate::paint(QPainter *painter, const QStyleOptionViewItem &option, cons
             title += "...";
         }
         painter->drawText(titlePointF,title);
+
         // persons
         titlePointF.setY(titlePointF.y()+fmSmall.height()-fmSmall.descent());
         painter->setFont(fontSmall);
         QString presenterPrefix = event->persons().count() < 2 ? "Presenter" : "Presenters";
         painter->drawText(titlePointF,presenterPrefix + ": " + event->persons().join(" and "));
+
         // track
         titlePointF.setY(titlePointF.y()+fmSmall.height()-fmSmall.descent());
         painter->drawText(titlePointF,"Track: " + Track::retrieveTrackName(event->trackId()));
     }
+
     else // doesn't have parent - time-groups' elements (top items)
     {
+        int numFav = numberOfFavourities(index);
+
+        QStyleOptionButton styleOptionButton;
+        styleOptionButton.rect = option.rect;
+        if (isExpanded(index)) styleOptionButton.state = QStyle::State_Sunken;
+        // styleOptionButton.text = qVariantValue<QString>(index.data());
+        qApp->style()->drawPrimitive(QStyle::PE_PanelButtonCommand, &styleOptionButton, painter, mViewPtr);
+        // qApp->style()->drawControl(QStyle::CE_PushButtonLabel, &styleOptionButton, painter, mViewPtr);
+        // qApp->style()->drawPrimitive(QStyle::PE_IndicatorArrowDown, &styleOptionButton, painter, mViewPtr);
+
         QFont fontSmall = option.font;
         fontSmall.setBold(true);
         fontSmall.setPixelSize(option.rect.height()*scaleFactor1);
@@ -204,45 +184,10 @@ void Delegate::paint(QPainter *painter, const QStyleOptionViewItem &option, cons
 
         int spacer = (fmSmall.boundingRect("999").width() < SPACER) ? SPACER : fmSmall.boundingRect("999").width();
 
-        QLinearGradient titleGradient(option.rect.topLeft(), option.rect.topRight());
-        bkgrColor = option.palette.color(QPalette::Highlight);
-        textColor = option.palette.color(QPalette::HighlightedText);
-        titleGradient.setColorAt(0.0, bkgrColor);
-        titleGradient.setColorAt(1.0, bkgrColor);
-
-        QPainterPath titlePath;
-        if(isExpanded(index))
-        {
-            titlePath.moveTo(option.rect.bottomLeft());
-            titlePath.lineTo(option.rect.topLeft()+QPoint(0, RADIUS));
-            titlePath.arcTo(option.rect.left(), option.rect.top(), 2*RADIUS, 2*RADIUS, 180, -90);
-            titlePath.lineTo(option.rect.topRight()-QPoint(RADIUS, 0));
-            titlePath.arcTo(option.rect.right()-2*RADIUS, option.rect.top(), 2*RADIUS, 2*RADIUS, 90, -90);
-            titlePath.lineTo(option.rect.bottomRight());
-            titlePath.closeSubpath();
-        }
-        else
-        {
-            titlePath.lineTo(option.rect.topLeft()+QPoint(0, RADIUS));
-            titlePath.arcTo(option.rect.left(), option.rect.top(), 2*RADIUS, 2*RADIUS, 180, -90);
-            titlePath.lineTo(option.rect.topRight()-QPoint(RADIUS, 0));
-            titlePath.arcTo(option.rect.right()-2*RADIUS, option.rect.top(), 2*RADIUS, 2*RADIUS, 90, -90);
-            titlePath.lineTo(option.rect.bottomRight()-QPoint(0, RADIUS));
-            titlePath.arcTo(option.rect.right()-2*RADIUS, option.rect.bottom()-2*RADIUS, 2*RADIUS, 2*RADIUS, 0, -90);
-            titlePath.lineTo(option.rect.bottomLeft()+QPoint(RADIUS, 0));
-            titlePath.arcTo(option.rect.left(), option.rect.bottom()-2*RADIUS, 2*RADIUS, 2*RADIUS, 270, -90);      
-            titlePath.closeSubpath();
-        }
-
-        painter->setBrush(titleGradient);
-        painter->setPen(borderPen);
-        painter->drawPath(titlePath);
-
         // draw icons
-        borderPen.setColor(textColor);
-        painter->setPen(borderPen);
+        painter->setPen(QPen(textColor));
         painter->setFont(fontSmall);
-        QImage *image = mControls[FavouriteControlOn]->image();
+        QImage *image = mControls[numFav ? FavouriteControlOn : FavouriteControlOff]->image();
         QPoint drawPoint =
             option.rect.topRight()
             - QPoint(
@@ -250,7 +195,7 @@ void Delegate::paint(QPainter *painter, const QStyleOptionViewItem &option, cons
                     - option.rect.height()/2 + image->height()/2);
         painter->drawImage(drawPoint,*image);
         painter->drawText(drawPoint+QPoint(image->width()+2, image->height() - 2),
-                QString::number(numberOfFavourities(index)));
+                QString::number(numFav));
 #ifdef MAEMO
         drawPoint.setX(drawPoint.x() - spacer - image->width());
         painter->drawImage(drawPoint,*mControls[AlarmControlOn]->image());
@@ -267,14 +212,9 @@ void Delegate::paint(QPainter *painter, const QStyleOptionViewItem &option, cons
                 option.rect.x()+SPACER,
                 option.rect.y()+option.rect.height()-fmBig.descent());
         painter->setFont(fontBig);
-
         painter->drawText(titlePointF,qVariantValue<QString>(index.data()));
     }
 
-    //// HIGHLIGHTING SELECTED ITEM
-    //if (option.state & QStyle::State_Selected)
-        //painter->fillRect(option.rect, option.palette.highlight());
-
     painter->restore();
 }
 
@@ -377,11 +317,15 @@ void Delegate::defineControls()
     // off
     mControls.insert(AlarmControlOff,
                     new Control(AlarmControlOff, QString(":icons/appointment-soon-off.png"), mControls[FavouriteControlOff]));
-#endif
-
+    // WARNING ICON
+    mControls.insert(WarningControl,
+                    new Control(WarningControl, QString(":icons/dialog-warning.png"), mControls[AlarmControlOff]));
+#else
     // WARNING ICON
     mControls.insert(WarningControl,
                     new Control(WarningControl, QString(":icons/dialog-warning.png"), mControls[FavouriteControlOn]));
+#endif
+
 }
 
 bool Delegate::isPointFromRect(const QPoint &aPoint, const QRect &aRect) const
index f24bea36e91b8b9b454af9af9a84a5e178193552..3f6e8f678786d8ca214edb4f7aa28874f4da094e 100644 (file)
@@ -20,9 +20,7 @@
 #ifndef DELEGATE_H
 #define DELEGATE_H
 
-#include <QItemDelegate>
-#include <QTreeView>
-#include <QPointer>
+#include <QtGui>
 
 class Delegate : public QItemDelegate
 {
index 074c51ab9486a7052cb7b1fffb273e308285a58c..280868f9374bfa75a3b2d3c0f6ac360186386197 100644 (file)
@@ -27,40 +27,68 @@ const QString EventModel::COMMA_SEPARATOR = ", ";
 EventModel::EventModel()
 { }
 
-void EventModel::createTimeGroups()
-{
-    mGroups.clear();
-    mParents.clear();
 
-    if (mEvents.empty())
-    {
-        return;
+void EventModel::Group::setTitle(const QList<Event>& mEvents) {
+    QTime startTime = mEvents.at(mFirstEventIndex).start().time();
+    QTime endTime(0, 0);
+    for (int i = mFirstEventIndex; i != mFirstEventIndex + mChildCount; ++i) {
+        endTime = qMax(mEvents.at(i).start().time().addSecs(mEvents.at(i).duration()), endTime);
     }
+    mTitle = QString("%1 - %2").arg(startTime.toString("HH:mm")).arg(endTime.toString("HH:mm"));
+}
 
-    const int timeSpan = 5400;
-
-    QTime startTime = mEvents.first().start().time();
-    mGroups << EventModel::Group(QString("%1 - %2").arg(startTime.toString("HH:mm"),
-        startTime.addSecs(timeSpan).toString("HH:mm")), 0);
-    QTime nextGroupTime = mEvents.first().start().time().addSecs(timeSpan);
 
-    for (int i=0; i<mEvents.count(); i++)
-    {
-        QTime eventTime = mEvents.at(i).start().time();
+// We want to group the events into "time slots/time groups" that
+// should start at full hours and have the duration of either
+// one hour or (if less than 3 events are in one time slot)
+// multiple of one hour.
+void EventModel::createTimeGroups()
+{
+    mGroups.clear();
+    mParents.clear();
+    if (mEvents.empty()) return;
+
+    const int minTimeSpan = 3600; // one hour
+    const int minChildCount = 3; // minimum number of events in one group
+
+    // Create the first time group. The events have to be sorted by start time at this point!
+    QTime groupStartTime(mEvents.first().start().time().hour(), 0);
+    QTime groupEndTime = groupStartTime.addSecs(mEvents.first().duration());
+    mGroups << EventModel::Group("", 0);
+    int timeSpan = minTimeSpan;
+
+    for (int i = 0; i != mEvents.count(); ++i) {
+        QTime eventStartTime = mEvents.at(i).start().time();
+        QTime eventEndTime = eventStartTime.addSecs(mEvents.at(i).duration());
+
+        if (eventStartTime >= groupStartTime.addSecs(timeSpan)) {
+            // a new group could be necessary
+            if (mGroups.last().mChildCount < minChildCount) {
+                // too few events in the group => no new group
+                // except a gap in time would occur that is longer than minTimeSpan
+                if (i > 0 && qMax(mEvents.at(i-1).start().time().addSecs(mEvents.at(i-1).duration()), groupEndTime).secsTo(eventStartTime) < minTimeSpan) {
+                    timeSpan += minTimeSpan;
+                    --i;
+                    continue; // repeat with the same event
+                }
+            }
 
-        if (nextGroupTime <= eventTime)
-        {
-            mGroups.last().mChildCount = i - mGroups.last().mFirstEventIndex;
-            mGroups << EventModel::Group(QString("%1 - %2").arg(nextGroupTime.toString("HH:mm"),
-                nextGroupTime.addSecs(timeSpan).toString("HH:mm")), i);
-            nextGroupTime = nextGroupTime.addSecs(timeSpan);
+            // a new group is necessary
+            mGroups.last().setTitle(mEvents);
+            groupStartTime = groupStartTime.addSecs(timeSpan);
+            groupEndTime = groupStartTime.addSecs(mEvents.at(i).duration());
+            mGroups << EventModel::Group("", i);
+            timeSpan = minTimeSpan;
         }
 
-        // add parent-child relation
+        // insert event into current group
         mParents[mEvents.at(i).id()] = mGroups.count() - 1;
+        mGroups.last().mChildCount += 1;
+        groupEndTime = qMax(eventEndTime, groupEndTime);
     }
 
-    mGroups.last().mChildCount = mEvents.count() - mGroups.last().mFirstEventIndex;
+    // the last group needs a title as well
+    mGroups.last().setTitle(mEvents);
 
     reset();
 }
index adf633cfdf6a3a3bb2819d3bba8bc70d9e0df79f..49d5dc7de01506b1bd97b08c8f6380ab3deae9c7 100644 (file)
@@ -58,6 +58,8 @@ private:
         QString mTitle;
         int mFirstEventIndex;
         int mChildCount;
+
+        void setTitle(const QList<Event>& mEvents);
     };
 
 private:
@@ -72,7 +74,7 @@ public slots:
 private:
     QList<Event> mEvents;
     QList<Group> mGroups;
-    QHash<int, int> mParents;
+    QHash<int, int> mParents; ///< eventId, groupId
 };
 
 #endif // EVENTMODEL_H
index 88933514eb886b950a758dbf7a4bd2b9db7e2813..6f514e91c848fc5a37164bfc0daa38a2a8295c4d 100644 (file)
@@ -70,10 +70,7 @@ bool TreeView::testForControlClicked(const QModelIndex &aIndex, const QPoint &aP
                 Event event = Event::getById(aIndex.data().toInt(),confId);
 
                 QList<Event> conflicts = Event::conflictEvents(event.id(),Conference::activeConference());
-                if(event.isFavourite())
-                    event.setFavourite(false);
-                else
-                    event.setFavourite(true);
+                event.setFavourite(!event.isFavourite());
                 event.update("favourite");
 
                 if(event.isFavourite())
index 4f5828dabde16bab9c91c74126cab9e57cb65944..85d32c29fc10cd00c26f2f074a2abb4ef02cefca 100644 (file)
@@ -93,8 +93,8 @@ T OrmRecord<T>::hydrate(const QSqlRecord& record)
 }
 
 // updates specified column 'col'
-// if the value is not specified  as an argument,
-// it's taken from the reford itself
+// if the value is not specified as an argument,
+// it's taken from the record itself
 // see also: setValue() method for more details
 template <typename T>
 void OrmRecord<T>::update(QString col, QVariant value)
@@ -106,7 +106,6 @@ void OrmRecord<T>::update(QString col, QVariant value)
     else // take 'col' value from the record; see setValue()
         query.bindValue(":col", convertToDb(this->value(col), this->value(col).type()));
     query.bindValue(":id", this->value("id"));
-    //query.bindValue(":id", convertToDb(value("id"), QVariant::Int));
     query.exec();
 }
 
index a8b32e9f1c3d22f240e613e16e11ebc90c0e77ae..205ecd080138cee58e4b1924b35ded09c81c5628 100644 (file)
@@ -58,8 +58,10 @@ QString SqlEngine::login(const QString &aDatabaseType, const QString &aDatabaseN
         file.open(QIODevice::ReadOnly | QIODevice::Text);
         QString allSqlStatements = file.readAll();
         foreach(QString sql, allSqlStatements.split(";")) {
+            if (sql.trimmed().length() == 0)     // do not execute empty queries like the last character from create_tables.sql
+                continue;
             QSqlQuery query(database);
-            if (!query.exec(sql)) qDebug() << "Could not execute query" << query.lastError();
+            if (!query.exec(sql)) qDebug() << "Could not execute query '" << sql << "' error:" << query.lastError();
         }
     }
     else