main_window.py 21.4 KB
Newer Older
1 2
from functools import partial

Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
3
from gettext import gettext as _
4
from gi.repository import Gio, GLib, Gdk, Gtk, Handy
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
5
from gi.repository import GLib
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
6 7 8 9 10
from gi.repository.GdkPixbuf import Pixbuf
import os
import ntpath
import threading

Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
11
from datetime import datetime, timedelta
12
from timetrack.activity import Activity
13
from timetrack.activity import ActivityWidget
14 15
from timetrack.activity import ActivitySummary
from timetrack.activity import ActivitySummaryWidget
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
16
from timetrack.edit import EditDialog
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
17

Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
18 19

class MainWindow(Gtk.ApplicationWindow):
20
    builder = NotImplemented
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
21
    application = NotImplemented
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
22 23
    current_activity = NotImplemented
    activity_list = NotImplemented
24
    activity_model = NotImplemented
25 26 27 28
    main_stack = NotImplemented
    report_stack = NotImplemented
    report_stack_switcher = NotImplemented
    reportbar = NotImplemented
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
29
    timer = NotImplemented
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
30 31
    quit_dialog = NotImplemented
    headerbar = NotImplemented
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
32 33 34 35 36 37
    start_button = NotImplemented
    stop_button = NotImplemented
    button_stack = NotImplemented
    activity_stack = NotImplemented
    activity_entry = NotImplemented
    activity_label = NotImplemented
38
    comments = None
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
39
    start_date = None
40
    activity_id = None
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
41

Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
42 43 44 45
    report_day_list = NotImplemented
    report_week_list = NotImplemented
    report_month_list = NotImplemented

46 47 48 49
    report_day_model = NotImplemented
    report_week_model = NotImplemented
    report_month_model = NotImplemented

50 51 52 53 54
    report_left = NotImplemented
    report_right = NotImplemented
    report_label = NotImplemented

    report_calendar = NotImplemented
55
    report_total = NotImplemented
56 57 58 59 60 61
    disable_calendar_change = False

    report_day_date = datetime.now()
    report_week_date = datetime.now()
    report_month_date = datetime.now()

62 63 64 65
    report_total_day = 0
    report_total_week = 0
    report_total_month = 0

Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
66 67 68 69
    new_action = NotImplemented
    edit_action = NotImplemented
    remove_action = NotImplemented

70 71 72 73 74
    current_name = NotImplemented
    current_hour = NotImplemented
    current_minute = NotImplemented
    current_day = NotImplemented

Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
75 76 77 78 79
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.logging_manager = kwargs['application'].get_logger()

        self.assemble_window()
80 81
        self.set_size_request(-1, 500)

Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
82
    def assemble_window(self):
83 84 85
        self.builder = Gtk.Builder()
        self.builder.add_from_resource("/net/danigm/timetrack/main_window.ui")

Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
86
        self.create_headerbar()
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
87
        self.create_container()
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
88 89 90
        self.custom_css()

    def create_headerbar(self):
91
        self.headerbar = self.builder.get_object("headerbar")
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
92 93
        self.set_titlebar(self.headerbar)

94 95 96 97 98 99
        self.button_stack = self.builder.get_object('button-stack')
        self.activity_stack = self.builder.get_object('activity-stack')
        self.start_button = self.builder.get_object('start-button')
        self.stop_button = self.builder.get_object('stop-button')
        self.activity_entry = self.builder.get_object('activity-entry')
        self.activity_label = self.builder.get_object('activity-label')
100
        self.activity_entry_buffer = self.activity_entry.get_buffer()
101
        self.activity_entry.connect("activate", self.startstop_activity)
102 103
        self.activity_entry_buffer.connect("inserted-text", self.check_enable_start)
        self.activity_entry_buffer.connect("deleted-text", self.check_enable_start)
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
104

Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
105 106
        if Gio.Application.get_default().development_mode is True:
            context = self.get_style_context()
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
107 108
            #context.add_class("devel")

109
    # TODO: Add comments
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
110
    def create_container(self):
111
        self.main_stack = self.builder.get_object('main-stack')
112

113 114
        self.timer = self.builder.get_object('timer')
        self.activity_list = self.builder.get_object('activity-list')
115 116 117
        self.activity_model = Gio.ListStore()
        self.activity_list.bind_model(self.activity_model,
                                      self.create_activity_widget)
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
118

Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
119 120 121
        self.activity_list.connect("selected-rows-changed", self.update_actions,
                                   None)

122 123 124 125 126 127 128 129 130 131 132 133
        self.create_current_popup()
        self.create_report()

        self.add(self.main_stack)
        self.show_all()

    def create_current_popup(self):
        self.current_name = self.builder.get_object('current-name')
        self.current_hour = self.builder.get_object('current-hour')
        self.current_minute = self.builder.get_object('current-minute')
        self.current_day = self.builder.get_object('current-day')
        self.current_timer = self.builder.get_object('current-timer')
134
        self.current_comments = self.builder.get_object('current-comments')
135 136 137 138 139 140 141 142

        self.current_name.bind_property('text', self.activity_label, 'label')
        self.timer.bind_property('label', self.current_timer, 'label')

        self.current_name.connect('changed', self.change_current)
        self.current_hour.connect('changed', self.change_current)
        self.current_minute.connect('changed', self.change_current)
        self.current_day.connect('day-selected', self.change_current)
143
        self.current_comments.get_buffer().connect('changed', self.change_current)
144 145 146 147 148 149 150 151 152 153

    def create_report(self):
        self.report_stack = self.builder.get_object('report-stack')
        self.report_stack.connect("notify::visible-child", self.report_changed)

        self.reportbar = self.builder.get_object("reportbar")
        self.report_left = self.builder.get_object('report-left')
        self.report_right = self.builder.get_object('report-right')
        self.report_label = self.builder.get_object('report-date')
        self.report_calendar = self.builder.get_object('report-calendar')
154 155
        self.report_calendar.connect("day-selected", self.report_change_day)

156
        self.report_total = self.builder.get_object('report-total')
157

158 159 160
        self.report_day_list = self.builder.get_object('report-day-list')
        self.report_week_list = self.builder.get_object('report-week-list')
        self.report_month_list = self.builder.get_object('report-month-list')
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
161

162 163 164 165 166 167 168 169 170 171 172
        self.report_day_model = Gio.ListStore()
        self.report_week_model = Gio.ListStore()
        self.report_month_model = Gio.ListStore()

        self.report_day_list.bind_model(self.report_day_model,
                                        self.create_activity_summary_widget)
        self.report_week_list.bind_model(self.report_week_model,
                                        self.create_activity_summary_widget)
        self.report_month_list.bind_model(self.report_month_model,
                                        self.create_activity_summary_widget)

173
        self.report_filter = self.builder.get_object('report-filter')
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
174 175
        self.report_filter.connect("activate", self.filter_report)

Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
176 177 178 179 180 181 182 183 184 185 186
    def set_headerbar(self):
        self.set_titlebar(self.headerbar)

    def get_headerbar(self):
        return self.headerbar

    def custom_css(self):
        screen = Gdk.Screen.get_default()

        css_provider = Gtk.CssProvider()
        css_provider_resource = Gio.File.new_for_uri(
187
            "resource:///net/danigm/timetrack/timetrack.css")
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
188 189 190 191 192
        css_provider.load_from_file(css_provider_resource)

        context = Gtk.StyleContext()
        context.add_provider_for_screen(
            screen, css_provider, Gtk.STYLE_PROVIDER_PRIORITY_USER)
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
193 194 195

    def add_actions(self):
        start_action = Gio.SimpleAction.new("activity.start", None)
196
        start_action.connect("activate", self.startstop_activity)
197 198
        start_action.set_enabled(False)
        self.start_action = start_action
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
199 200 201
        self.application.add_action(start_action)

        stop_action = Gio.SimpleAction.new("activity.stop", None)
202
        stop_action.connect("activate", self.startstop_activity)
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
203 204
        self.application.add_action(stop_action)

205 206 207 208 209 210 211 212
        action = Gio.SimpleAction.new("report", None)
        action.connect("activate", self.show_report)
        self.application.add_action(action)

        action = Gio.SimpleAction.new("list", None)
        action.connect("activate", self.show_list)
        self.application.add_action(action)

Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
        # new
        action = Gio.SimpleAction.new("new", None)
        action.connect("activate", self.new_activity)
        self.new_action = action
        self.application.add_action(action)

        # edit
        action = Gio.SimpleAction.new("edit", None)
        action.connect("activate", self.edit_activity)
        action.set_enabled(False)
        self.edit_action = action
        self.application.add_action(action)

        # remove
        action = Gio.SimpleAction.new("remove", None)
        action.connect("activate", self.remove_activity)
        action.set_enabled(False)
        self.remove_action = action
        self.application.add_action(action)

233 234 235 236 237 238 239 240 241 242 243
        # report actions
        action = Gio.SimpleAction.new("report-left", None)
        action.connect("activate", self.report_go_left)
        self.application.add_action(action)
        action = Gio.SimpleAction.new("report-right", None)
        action.connect("activate", self.report_go_right)
        self.application.add_action(action)
        action = Gio.SimpleAction.new("report-today", None)
        action.connect("activate", self.report_go_today)
        self.application.add_action(action)

244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267
        action = Gio.SimpleAction.new("report-day", None)
        action.connect("activate", partial(self.report_show, "day"))
        self.application.add_action(action)

        action = Gio.SimpleAction.new("report-week", None)
        action.connect("activate", partial(self.report_show, "week"))
        self.application.add_action(action)

        action = Gio.SimpleAction.new("report-month", None)
        action.connect("activate", partial(self.report_show, "month"))
        self.application.add_action(action)

        action = Gio.SimpleAction.new("report-filter", None)
        action.connect("activate", self.filter)
        self.application.add_action(action)

    def filter(self, *args, **kwargs):
        self.show_report()
        self.report_filter.grab_focus()

    def report_show(self, name, *args, **kwargs):
        self.show_report()
        self.report_stack.set_visible_child_name(name)

268 269 270
    def show_report(self, *args, **kwargs):
        self.main_stack.set_visible_child_name("report")
        self.set_titlebar(self.reportbar)
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
271 272 273
        self.fill_report()

    def fill_report(self):
274
        self.report_label.set_text(self.report_day_date.strftime("%d/%M/%Y"))
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
275 276 277
        self.fill_report_day()
        self.fill_report_week()
        self.fill_report_month()
278
        self.report_changed()
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
279 280

    def fill_report_day(self):
281
        now = self.report_day_date
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
282 283
        s = datetime(now.year, now.month, now.day)
        e = s + timedelta(days=1)
284
        r = self.fill_report_generic(s, e, self.report_day_model)
285
        self.report_total_day = r
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
286 287

    def fill_report_week(self):
288
        now = self.report_week_date
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
289 290 291
        s = datetime(now.year, now.month, now.day)
        s -= timedelta(days=s.isoweekday() - 1)
        e = s + timedelta(days=7)
292
        r = self.fill_report_generic(s, e, self.report_week_model)
293
        self.report_total_week = r
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
294 295

    def fill_report_month(self):
296
        now = self.report_month_date
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
297
        s = datetime(now.year, now.month, 1)
298 299 300 301 302 303 304 305 306
        y = now.year
        m = now.month + 1
        if m > 12:
            m = 1
            y += 1
        elif m < 1:
            m = 12
            y -= 1
        e = datetime(y, m, 1)
307
        r = self.fill_report_generic(s, e, self.report_month_model)
308
        self.report_total_month = r
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
309

310
    def fill_report_generic(self, start, end, model):
311
        total = 0
312
        model.remove_all()
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
313

Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
314 315 316
        filter = self.report_filter.get_text()
        query = self.application.db.report(start=start, end=end, activity=filter)
        for (act, seconds) in query:
317
            total += seconds
318
            model.append(ActivitySummary(name=act, seconds=seconds))
319

320 321
        return total

322 323 324
    def show_list(self, *args, **kwargs):
        self.main_stack.set_visible_child_name("main")
        self.set_titlebar(self.headerbar)
325 326 327
        self.activity_entry.grab_focus()

    def startstop_activity(self, *args, **kwargs):
328 329 330 331
        if self.activity_entry_buffer.get_length() > 0:
            if self.start_date:
                self.stop_activity()
                return
332

333 334
            self.activity_stack.set_visible_child_name("working")
            self.button_stack.set_visible_child_name("working")
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
335

336
            self.start_date = datetime.now()
337
            self.comments = ""
338 339 340
            activity = self.activity_entry.get_text()
            self.activity_label.set_text(activity)
            GLib.timeout_add(1000, self.update_timer, None)
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
341

342
            activity = Activity(id=None, name=activity, start=self.start_date, stop=None)
343
            self.update_current_popup(activity)
344 345 346 347 348
            self.activity_id = self.application.db.store(activity)

    def check_enable_start(self, *args, **kwargs):
        self.start_action.set_enabled(
            self.activity_entry_buffer.get_length() > 0)
349

Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
350 351 352
    def stop_activity(self, *args, **kwargs):
        self.activity_stack.set_visible_child_name("waiting")
        self.button_stack.set_visible_child_name("waiting")
353
        self.timer.set_text("00:00:00")
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
354

355 356 357
        name = self.activity_label.get_text()
        start = self.start_date
        stop = datetime.now()
358 359
        activity = Activity(id=self.activity_id, name=name,
                            start=start, stop=stop, comments=self.comments)
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
360 361

        self.application.db.set_stop(self.activity_id, stop, activity.seconds)
362

363
        self.insert_activity(activity)
364
        self.comments = ""
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
365
        self.start_date = None
366
        self.activity_id = None
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
367 368 369 370 371 372

    def update_timer(self, *args, **kwargs):
        if not self.start_date:
            return False

        now = datetime.now()
373 374 375
        diff = int((now - self.start_date).total_seconds())
        timepass = self.seconds_to_time(diff)
        self.timer.set_text(timepass)
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
376 377

        return True
378 379 380

    def load_last(self):
        for act in self.application.db.get_last():
381
            self.insert_activity(act)
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
382 383 384 385 386 387 388 389

    def seconds_to_time(self, seconds):
        m = seconds // 60
        s = seconds % 60
        h = m // 60
        m = m % 60

        return "{:02d}:{:02d}:{:02d}".format(h, m, s)
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
390 391 392 393 394 395 396 397 398 399

    def update_actions(self, *args, **kwargs):
        if self.activity_list.get_selected_rows():
            self.edit_action.set_enabled(True)
            self.remove_action.set_enabled(True)
        else:
            self.edit_action.set_enabled(False)
            self.remove_action.set_enabled(False)

    def edit_activity(self, *args, **kwargs):
400 401 402
        selected = self.activity_list.get_selected_row()
        index = selected.get_index()
        act = self.activity_model.get_item(index)
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
403 404

        dialog = EditDialog(self.application.db, self)
405
        result = dialog.open(act.id)
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
406
        if result:
407 408
            self.activity_model.remove(index)
            self.insert_activity(result)
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
409 410 411 412 413

    def new_activity(self, *args, **kwargs):
        dialog = EditDialog(self.application.db, self)
        act = dialog.open()
        if act:
414
            self.insert_activity(act)
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
415 416

    def remove_activity(self, *args, **kwargs):
417 418 419 420
        selected = self.activity_list.get_selected_row()
        index = selected.get_index()
        act = self.activity_model.get_item(index)
        aid = act.id
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
421 422 423 424 425 426 427 428 429 430 431 432

        confirm = Gtk.MessageDialog(text=_("Are you sure?"),
                                    buttons=Gtk.ButtonsType.YES_NO)
        confirm.set_transient_for(self)
        confirm.set_attached_to(self)
        confirm.set_destroy_with_parent(True)
        confirm.set_type_hint(Gdk.WindowTypeHint.DIALOG)
        confirm.set_modal(True)

        resp = confirm.run()
        if resp == Gtk.ResponseType.YES:
            self.application.db.delete(aid)
433
            self.activity_model.remove(index)
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
434
        confirm.close()
435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483

    def report_go_left(self, *args, **kwargs):
        selected = self.report_stack.get_visible_child_name()
        if selected == 'day':
            self.report_day_date -= timedelta(days=1)
        elif selected == 'week':
            self.report_week_date -= timedelta(days=7)
        elif selected == 'month':
            date = self.report_month_date
            y, m = date.year, date.month
            m = m - 1
            if m < 1:
                m = 12
                y -= 1
            self.report_month_date = datetime(y, m, 1)
        self.fill_report()

    def report_go_right(self, *args, **kwargs):
        selected = self.report_stack.get_visible_child_name()
        if selected == 'day':
            self.report_day_date += timedelta(days=1)
        elif selected == 'week':
            self.report_week_date += timedelta(days=7)
        elif selected == 'month':
            date = self.report_month_date
            y, m = date.year, date.month
            m = m + 1
            if m > 12:
                m = 1
                y += 1
            self.report_month_date = datetime(y, m, 1)
        self.fill_report()

    def report_go_today(self, *args, **kwargs):
        selected = self.report_stack.get_visible_child_name()
        if selected == 'day':
            self.report_day_date = datetime.now()
        elif selected == 'week':
            self.report_week_date = datetime.now()
        elif selected == 'month':
            n = datetime.now()
            self.report_month_date = datetime(n.year, n.month, 1)
        self.fill_report()

    def report_changed(self, *args, **kwargs):
        self.disable_calendar_change = True
        self.report_calendar.clear_marks()

        text = ""
484
        total = 0
485 486 487 488 489 490
        selected = self.report_stack.get_visible_child_name()
        if selected == 'day':
            text = self.report_day_date.strftime("%d/%m/%Y")
            self.report_calendar.select_month(self.report_day_date.month - 1,
                                              self.report_day_date.year)
            self.report_calendar.select_day(self.report_day_date.day)
491 492
            total = self.report_total_day

493 494 495 496 497 498 499 500 501 502 503 504
        elif selected == 'week':
            now = self.report_week_date
            s = datetime(now.year, now.month, now.day)
            s -= timedelta(days=s.isoweekday() - 1)
            self.report_week_date = s
            e = s + timedelta(days=6)
            text = s.strftime("%d/%m") + "-" + e.strftime("%d/%m")
            self.report_calendar.select_month(s.month - 1, s.year)
            self.report_calendar.select_day(s.day)
            while s <= e:
                self.report_calendar.mark_day(s.day)
                s += timedelta(days=1)
505 506
            total = self.report_total_week

507 508 509 510 511 512 513 514 515 516 517
        elif selected == 'month':
            now = self.report_month_date
            s = datetime(now.year, now.month, 1)
            self.report_month_date = now
            text = s.strftime("%m/%Y")
            self.report_calendar.select_month(s.month - 1, s.year)
            self.report_calendar.select_day(s.day)
            m = s.month
            while s.month == m:
                self.report_calendar.mark_day(s.day)
                s += timedelta(days=1)
518 519
            total = self.report_total_month

520
        self.report_label.set_text(text)
521
        self.report_total.set_text(self.seconds_to_time(total))
522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540

        self.disable_calendar_change = False

    def report_change_day(self, *args, **kwargs):
        if self.disable_calendar_change:
            return

        new_date = self.report_calendar.get_date()
        d = datetime(new_date.year, new_date.month + 1, new_date.day)

        selected = self.report_stack.get_visible_child_name()
        if selected == 'day':
            self.report_day_date = d
        elif selected == 'week':
            self.report_week_date = d
        elif selected == 'month':
            self.report_month_date = datetime(d.year, d.month, 1)

        self.fill_report()
Daniel Garcia Moreno's avatar
Daniel Garcia Moreno committed
541 542 543

    def filter_report(self, *args, **kwargs):
        self.fill_report()
544 545 546 547 548 549 550

    def insert_activity(self, activity):
        self.activity_model.insert_sorted(activity,
                                          lambda a, b: a.start < b.start)

    def create_activity_widget(self, item):
        return ActivityWidget(item)
551 552 553

    def create_activity_summary_widget(self, item):
        return ActivitySummaryWidget(item)
554 555 556 557 558

    def update_current_popup(self, activity):
        self.current_name.set_text(activity.name)
        self.current_hour.set_value(activity.start.hour)
        self.current_minute.set_value(activity.start.minute)
559 560 561 562 563
        self.current_day.select_month(activity.start.month - 1,
                                      activity.start.year)
        self.current_day.select_day(activity.start.day)

        self.current_comments.get_buffer().set_text(activity.comments)
564 565 566 567 568 569 570 571

    def change_current(self, *args, **kwargs):
        if not self.activity_id or not self.start_date:
            return

        new_date = self.current_day.get_date()
        name = self.current_name.get_text()

572 573 574
        comments_buf = self.current_comments.get_buffer()
        comments_start = comments_buf.get_start_iter()
        comments_end = comments_buf.get_end_iter()
575
        self.comments = comments_buf.get_text(comments_start, comments_end, False)
576

577 578 579 580 581 582 583 584
        self.start_date = datetime(new_date.year,
                                   new_date.month + 1,
                                   new_date.day,
                                   int(self.current_hour.get_value()),
                                   int(self.current_minute.get_value()))

        activity = Activity(id=self.activity_id,
                            name=name,
585 586
                            start=self.start_date,
                            stop=None,
587
                            comments=self.comments)
588
        self.application.db.update(activity)