コード例 #1
0
    def init_calendario(self):
        calendario = QCalendarWidget(self)
        currentMonth = datetime.now().month
        currentYear = datetime.now().year

        calendario.setMinimumDate(QDate(currentYear, currentMonth, 1))
        calendario.setMaximumDate(
            QDate(currentYear + 1, currentMonth,
                  calendar.monthrange(currentYear, currentMonth)[1]))
        calendario.setSelectedDate(QDate(currentYear, currentMonth, 1))

        calendario.setFont(QFont('Georgia', 10))
        calendario.setStyleSheet('background-color: lightblue')

        calendario.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        calendario.setGeometry(200, 200, 300, 200)
        calendario.setGridVisible(True)
        return calendario
コード例 #2
0
class Reservations(QWidget):
    """
    Klasa odpowiedzialna za widget klienci
    """
    def __init__(self, parent, db):
        super(QWidget, self).__init__(parent)
        self.parent = parent
        self.btn_mod = QPushButton('Zmiana statusu')
        self.btn_usun = QPushButton('Usuń')
        self.btn_dodaj = QPushButton('Dodaj')
        self.lbl_klient_ = QLabel('')
        self.lbl_usluga_ = QLabel('')
        self.lbl_termin_ = QDateTimeEdit()
        self.gb_layout = QVBoxLayout()
        self.kalendarz = QCalendarWidget()
        self.view_u = QTableView()
        self.view_k = QTableView()
        self.view_p = QTableView()
        self.view = QTableView()
        self.proxy_u = QSortFilterProxyModel(self)
        self.proxy_k = QSortFilterProxyModel(self)
        self.proxy_p = QSortFilterProxyModel(self)
        self.proxy = QSortFilterProxyModel(self)
        self.id_klient = -1
        self.id_usluga = -1
        self.id_pracownik = -1
        self.id_rezerwacje = -1
        self.data = None
        self.data_do = None
        self.dzien_tyg = 0
        self.czas = []

        # Lista składana przycisków godzin
        self.btn_godz = [QPushButton(str(i + 1)) for i in range(16)]

        # Parametry połączenia z bazą
        self.model_u = QSqlTableModel(self, db)
        self.model_k = QSqlTableModel(self, db)
        self.model_p = QSqlTableModel(self, db)
        self.model = QSqlTableModel(self, db)

        self.initUI()

    def initUI(self):
        """
        Inicjuje UI
        """
        self.view_u.setObjectName('Usługi')
        self.view_k.setObjectName('Klienci')
        self.view_p.setObjectName('Pracownicy')
        self.view.setObjectName('Rezerwacje')
        self.table_init_u()
        self.table_init_k()
        self.table_init_p()
        self.table_init()
        self.btn_mod.setDisabled(True)
        self.btn_usun.setDisabled(True)
        self.btn_dodaj.setDisabled(True)

        # Tworzenie kontrolek
        lbl_wysz_u = QLabel('Wyszukaj usługę:')
        lbl_wysz_k = QLabel('Wyszukaj klienta:')
        lbl_wysz_p = QLabel('Wyszukaj pracownika:')
        txt_wysz_u = QLineEdit(self)
        txt_wysz_k = QLineEdit(self)
        txt_wysz_p = QLineEdit(self)
        lbl_klient = QLabel('Klient:')
        lbl_usluga = QLabel('Usługa:')
        lbl_termin = QLabel('Termin:')

        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.kalendarz.sizePolicy().hasHeightForWidth())
        self.kalendarz.setSizePolicy(sizePolicy)

        # Tworzenie widoków
        centralbox = QHBoxLayout()
        hbox_wysz_u = QHBoxLayout()
        hbox_wysz_k = QHBoxLayout()
        hbox_wysz_p = QHBoxLayout()
        vbox_u = QVBoxLayout()
        vbox_k = QVBoxLayout()
        vbox_p = QVBoxLayout()
        vbox_right = QVBoxLayout()
        hbox_btn = QHBoxLayout()
        hbox_k = QHBoxLayout()
        hbox_u = QHBoxLayout()
        hbox_t = QHBoxLayout()
        vbox_cal = QVBoxLayout()
        groupbox = QGroupBox('Godziny:')
        groupbox.setLayout(self.gb_layout)
        hbox_left = QHBoxLayout()

        # Metody
        self.lbl_termin_.setCalendarWidget(self.kalendarz)
        self.lbl_termin_.setDate(self.kalendarz.selectedDate())
        self.dzien_tyg = self.kalendarz.selectedDate().dayOfWeek()
        txt_wysz_u.textChanged.connect(self.searching_u)
        txt_wysz_k.textChanged.connect(self.searching_k)
        txt_wysz_p.textChanged.connect(self.searching_p)
        self.view_k.clicked.connect(lambda: self.clicked_table(self.view_k))
        self.view_p.clicked.connect(lambda: self.clicked_table(self.view_p))
        self.view_u.clicked.connect(lambda: self.clicked_table(self.view_u))
        self.view.clicked.connect(lambda: self.clicked_table(self.view))
        self.kalendarz.clicked.connect(self.show_data)
        self.btn_dodaj.clicked.connect(self.add)
        self.btn_mod.clicked.connect(self.modify)
        self.btn_usun.clicked.connect(self.remove)

        # Ustawianie widoków
        hbox_wysz_k.addWidget(lbl_wysz_k)
        hbox_wysz_k.addWidget(txt_wysz_k)
        hbox_wysz_p.addWidget(lbl_wysz_p)
        hbox_wysz_p.addWidget(txt_wysz_p)
        hbox_wysz_u.addWidget(lbl_wysz_u)
        hbox_wysz_u.addWidget(txt_wysz_u)
        vbox_u.addLayout(hbox_wysz_u)
        vbox_u.addWidget(self.view_u)
        vbox_k.addLayout(hbox_wysz_k)
        vbox_k.addWidget(self.view_k)
        vbox_p.addLayout(hbox_wysz_p)
        vbox_p.addWidget(self.view_p)
        vbox_right.addLayout(vbox_p)
        vbox_right.addLayout(vbox_u)
        vbox_right.addLayout(vbox_k)
        hbox_btn.addWidget(self.btn_usun)
        hbox_btn.addWidget(self.btn_mod)
        hbox_k.addWidget(lbl_klient)
        hbox_k.addWidget(self.lbl_klient_)
        hbox_u.addWidget(lbl_usluga)
        hbox_u.addWidget(self.lbl_usluga_)
        hbox_t.addWidget(lbl_termin)
        hbox_t.addWidget(self.lbl_termin_)
        vbox_cal.addWidget(self.kalendarz)
        vbox_cal.addLayout(hbox_u)
        vbox_cal.addLayout(hbox_t)
        vbox_cal.addLayout(hbox_k)
        self.view.setSizePolicy(
            QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum))
        vbox_cal.addWidget(self.view)
        vbox_cal.addLayout(hbox_btn)
        vbox_cal.addWidget(self.btn_dodaj)
        hbox_left.addLayout(vbox_cal)
        hbox_left.addWidget(groupbox)
        centralbox.addLayout(hbox_left)
        centralbox.addLayout(vbox_right)

        self.setLayout(centralbox)
        self.show()

    def show_data(self):
        self.lbl_termin_.setDate(self.kalendarz.selectedDate())
        self.dzien_tyg = self.kalendarz.selectedDate().dayOfWeek()
        self.clicked_table(self.view_p)

    def table_init_u(self):
        """
        Inicjuje wygląd tabeli usługi
        """
        # self.model_u.setTable('uslugi')
        query = QSqlQuery(
            'SELECT uslugi.uslugi_id, uslugi.nazwa, uslugi.cena, date_format(uslugi.czas, "%H:%i") AS czas FROM uslugi NATURAL JOIN uzytkownik_usluga WHERE uzytkownik_usluga.uzytkownik_id = '
            + str(self.id_pracownik) + ';')
        self.model_u.setQuery(query)
        # self.model_u.select()

        self.proxy_u.setSourceModel(self.model_u)

        naglowki = {
            'uslugi_id': 'ID',
            'nazwa': 'Nazwa',
            'cena': 'Cena',
            "czas": 'Czas',
        }
        # Ustawianie nagłówków
        ilosc_kolumn = self.model_u.columnCount()
        for i in range(ilosc_kolumn):
            nazwa_kolumn = self.model_u.headerData(i, Qt.Horizontal)
            self.model_u.setHeaderData(i, Qt.Horizontal,
                                       naglowki[nazwa_kolumn])

        self.view_u.setSizeAdjustPolicy(
            QAbstractScrollArea.AdjustToContentsOnFirstShow)
        self.view_u.setSortingEnabled(True)
        self.view_u.setAlternatingRowColors(True)

        # Wczytanie danych
        self.view_u.setModel(self.proxy_u)
        self.view_u.hideColumn(0)
        self.view_u.sortByColumn(1, Qt.AscendingOrder)
        self.view_u.setEditTriggers(QAbstractItemView.NoEditTriggers)

    def table_init_k(self):
        """
        Inicjuje wygląd tabeli klienta
        """
        self.model_k.setTable('klienci')
        query = QSqlQuery(
            'SELECT klienci_id, imie, nazwisko, email, telefon, ulica, numer_mieszkania, miejscowosc, poczta FROM '
            'klienci;')
        self.model_k.setQuery(query)
        # self.model_k.select()

        self.proxy_k.setSourceModel(self.model_k)

        naglowki = {
            'klienci_id': 'ID',
            'imie': 'Imię',
            'nazwisko': 'Nazwisko',
            "email": 'Email',
            'telefon': 'Telefon',
            'ulica': 'Ulica',
            'numer_mieszkania': 'Numer mieszkania',
            'miejscowosc': 'Miejscowosc',
            'poczta': 'Kod pocztowy',
        }
        # Ustawianie nagłówków
        ilosc_kolumn = self.model_k.columnCount()
        for i in range(ilosc_kolumn):
            nazwa_kolumn = self.model_k.headerData(i, Qt.Horizontal)
            self.model_k.setHeaderData(i, Qt.Horizontal,
                                       naglowki[nazwa_kolumn])

        self.view_k.setSizeAdjustPolicy(
            QAbstractScrollArea.AdjustToContentsOnFirstShow)
        self.view_k.setSortingEnabled(True)
        self.view_k.setAlternatingRowColors(True)

        # Wczytanie danych
        self.view_k.setModel(self.proxy_k)
        self.view_k.hideColumn(0)
        self.view_k.sortByColumn(1, Qt.AscendingOrder)
        self.view_k.setEditTriggers(QAbstractItemView.NoEditTriggers)

    def table_init_p(self):
        """
        Inicjuje wygląd tabeli pracownik
        """
        self.model_p.setTable('uzytkownik')
        query = QSqlQuery(
            'SELECT uzytkownik_id,  imie, nazwisko FROM uzytkownik WHERE '
            'pracownik = 1;')
        self.model_p.setQuery(query)
        # self.model_p.select()

        self.proxy_p.setSourceModel(self.model_p)

        naglowki = {
            'uzytkownik_id': 'ID',
            'imie': 'Imię',
            "nazwisko": 'Nazwisko',
        }
        # Ustawianie nagłówków
        ilosc_kolumn = self.model_p.columnCount()
        for i in range(ilosc_kolumn):
            nazwa_kolumn = self.model_p.headerData(i, Qt.Horizontal)
            self.model_p.setHeaderData(i, Qt.Horizontal,
                                       naglowki[nazwa_kolumn])

        self.view_p.setSizeAdjustPolicy(
            QAbstractScrollArea.AdjustToContentsOnFirstShow)
        self.view_p.setSortingEnabled(True)
        self.view_p.setAlternatingRowColors(True)

        # Wczytanie danych
        self.view_p.setModel(self.proxy_p)
        self.view_p.hideColumn(0)
        self.view_p.sortByColumn(1, Qt.AscendingOrder)
        self.view_p.setEditTriggers(QAbstractItemView.NoEditTriggers)

    def table_init(self):
        """
        Inicjuje wygląd tabeli
        """
        query = QSqlQuery(
            'SELECT wizyty.wizyty_id, CONCAT(klienci.imie, " ", klienci.nazwisko) AS klient, uslugi.nazwa, '
            'wizyty.rezerwacja_od, wizyty.rezerwacja_do, wizyty.status FROM klienci, uslugi NATURAL JOIN wizyty WHERE wizyty.rezerwacja_od > CURRENT_TIMESTAMP AND wizyty.uzytkownik_id = '
            + str(self.id_pracownik) + ';')
        self.model.setQuery(query)
        self.proxy.setSourceModel(self.model)

        naglowki = {
            'wizyty_id': 'ID',
            'klient': 'Klient',
            'nazwa': 'Usługa',
            'rezerwacja_od': 'Rezerwacja od',
            "rezerwacja_do": 'Rezerwacja do',
            'status': 'Status rezerwacji'
        }
        # Ustawianie nagłówków
        ilosc_kolumn = self.model.columnCount()
        for i in range(ilosc_kolumn):
            nazwa_kolumn = self.model.headerData(i, Qt.Horizontal)
            self.model.setHeaderData(i, Qt.Horizontal, naglowki[nazwa_kolumn])

        self.view.setSizeAdjustPolicy(
            QAbstractScrollArea.AdjustToContentsOnFirstShow)
        self.view.setSortingEnabled(True)
        self.view.setAlternatingRowColors(True)

        # Wczytanie danych
        self.view.setModel(self.proxy)
        self.view.hideColumn(0)
        self.view.sortByColumn(4, Qt.AscendingOrder)
        self.view.setEditTriggers(QAbstractItemView.NoEditTriggers)

    def clicked_table(self, view):
        """
        Metoda edytująca zaznaczone wiersze - Wstawia wartości z wierszy w odpowiednie pola
        """
        index = (view.selectionModel().currentIndex())
        if view.objectName() == 'Klienci':
            self.id_klient = index.sibling(index.row(), 0).data()
            self.lbl_klient_.setText('<b>' +
                                     index.sibling(index.row(), 1).data() +
                                     ' ' +
                                     index.sibling(index.row(), 2).data() +
                                     '</b>')
        elif view.objectName() == 'Usługi':
            self.id_usluga = index.sibling(index.row(), 0).data()
            self.lbl_usluga_.setText('<b>' +
                                     index.sibling(index.row(), 1).data() +
                                     '</b>')
            self.data_do = index.sibling(index.row(), 3).data()
        elif view.objectName() == 'Rezerwacje':
            self.id_rezerwacje = index.sibling(index.row(), 0).data()
            if self.id_rezerwacje > 0:
                self.btn_mod.setEnabled(True)
                self.btn_usun.setEnabled(True)
        elif view.objectName() == 'Pracownicy':
            self.id_pracownik = index.sibling(index.row(), 0).data()
            self.czas = []
            for i in reversed(range(self.gb_layout.count())):
                self.gb_layout.itemAt(i).widget().setParent(None)
            czas = datetime.datetime(2000, 1, 1, 8, 0)
            dzien = {
                1: ('pon_od', 'pon_do'),
                2: ('wt_od', 'wt_do'),
                3: ('sr_od', 'sr_do'),
                4: ('czw_od', 'czw_do'),
                5: ('pt_od', 'pt_do'),
                6: ('sob_od', 'sob_do'),
                7: ('', '')
            }
            query = 'SELECT date_format({}, "%H") AS g_start, date_format({}, "%H") AS g_stop FROM godziny WHERE ' \
                    'uzytkownik_id = {};'.format(dzien[self.dzien_tyg][0], dzien[self.dzien_tyg][1], self.id_pracownik)
            wynik = query_to_db(query)
            if wynik:
                godzina_stop = (int(wynik[1]) - int(wynik[0])) * 2
                godzina = int(wynik[0])
                for btn in self.btn_godz:
                    btn.setEnabled(True)
            else:
                godzina_stop = 0
                godzina = 1
                for btn in self.btn_godz:
                    btn.setDisabled(True)
            minuta = 0
            czas = datetime.time(godzina, minuta)
            for i in range(godzina_stop):
                self.btn_godz[i].setText(czas.strftime("%H:%M"))
                self.czas.append(czas)
                self.btn_godz[i].setObjectName(str(i))
                self.gb_layout.addWidget(self.btn_godz[i])
                if i % 2 != 0:
                    godzina += 1
                    minuta = 0
                else:
                    minuta = 30
                czas = datetime.time(godzina, minuta)
            QMetaObject.connectSlotsByName(self)

            # Czyszczenie, odświeżanie
            self.refresh()
            query = QSqlQuery(
                'SELECT uslugi.uslugi_id, uslugi.nazwa, uslugi.cena, date_format(uslugi.czas, "%H:%i") AS czas FROM uslugi NATURAL JOIN uzytkownik_usluga WHERE uzytkownik_usluga.uzytkownik_id = '
                + str(self.id_pracownik) + ';')
            self.model_u.setQuery(query)
            self.lbl_klient_.setText('')
            self.lbl_usluga_.setText('')

        if self.id_klient > 0 and self.id_pracownik > 0 and self.id_usluga > 0:
            self.btn_dodaj.setEnabled(True)

    def if_checked(self, txt, q, val=None):
        """
        Sprawdza poprawność wprowadzonych damych.
        :param val: wartości do zapytania
        :param q: zapytanie query MySql
        :param txt: komunikat
        """
        if self.id_klient < 0 and self.id_pracownik < 0 and self.id_usluga < 0 and self.data is None:
            msg = QMessageBox(self)
            msg.setIcon(QMessageBox.Warning)
            msg.setText(txt)
            msg.setWindowTitle("Popraw dane")
            msg.exec_()
            return False
        else:
            print('Trwa zmiana w bazie danych')
            if val:
                print('Połączenie')
                query_to_db(q, val)
            else:
                print('Transakcja')
                return transaction_to_db(q)

            return True

    def refresh(self):
        """
        Odświeża widok tabeli rezerwacji
        """
        # Odświeżanie widoku tabeli
        query = QSqlQuery(
            'SELECT wizyty.wizyty_id, CONCAT(klienci.imie, " ", klienci.nazwisko) AS klient, uslugi.nazwa, '
            'wizyty.rezerwacja_od, wizyty.rezerwacja_do, wizyty.status FROM wizyty,klienci,uslugi WHERE wizyty.klienci_id= klienci.klienci_id AND wizyty.uslugi_id = uslugi.uslugi_id AND wizyty.rezerwacja_od > CURRENT_TIMESTAMP AND wizyty.uzytkownik_id = '
            + str(self.id_pracownik) + ';')
        self.model.setQuery(query)
        self.view.reset()

    def add(self):
        """
        Dodaje rezerwację do bazy danych i odświeża widok.
        """
        tekst = 'Nie wprowadzono wszystkich danych'
        self.data = self.lbl_termin_.dateTime().toString(Qt.ISODate)
        self.data_do = datetime.datetime.fromisoformat(
            self.data) + datetime.timedelta(
                hours=datetime.time.fromisoformat(self.data_do).hour,
                minutes=datetime.time.fromisoformat(self.data_do).minute)
        # Dodanie nowego użytkownika
        query = 'INSERT INTO wizyty (klienci_id, uslugi_id, uzytkownik_id, rezerwacja_od, rezerwacja_do, ' \
                'status) VALUES (%s, %s, %s, %s, %s, %s);'
        val = (self.id_klient, self.id_usluga, self.id_pracownik, self.data,
               str(self.data_do.isoformat()), 'oczekuje')
        print(val)

        if self.if_checked(tekst, query, val):
            msg = QMessageBox(self)
            msg.setIcon(QMessageBox.Information)
            msg.setText('Rezerwacja została dodana do bazy danych')
            msg.setWindowTitle("Dodano nową rezerwację")
            msg.exec_()
            self.refresh()

    def modify(self):
        """
        Zmienia status rezerwacji i odświeża widok.
        """
        tekst = 'Nie wprowadzono wszystkich danych'

        items = ('Oczekuje', 'Wykonana', 'Rezygnacja')
        item, ok = QInputDialog.getItem(self, "Wybierz status",
                                        "Wybierz nowy status rezerwacji",
                                        items, 0, False)

        if ok and item:
            # Zmodyfikowanie statusu
            query = 'UPDATE wizyty SET status = %s WHERE wizyty_id = %s;'
            val = (item.lower(), self.id_rezerwacje)

            if self.if_checked(tekst, query, val):
                msg = QMessageBox(self)
                msg.setIcon(QMessageBox.Information)
                msg.setText('Status rezerwacji został zmodyfikowany')
                msg.setWindowTitle("Zmodyfikowano status")
                msg.exec_()
                self.refresh()

    def remove(self):
        """
        Usuwa rezerwację z bazy danych
        """
        test = 'Błąd! Nie można usunąć danej rezerwacji!'
        query = 'DELETE FROM wizyty WHERE wizyty_id = %s'
        val = (self.id_rezerwacje, )
        ret = QMessageBox.question(
            self, 'Usuwanie rezerwacji',
            "Czy na pewno chcesz usunąć daną rezerwację klienta?",
            QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
        if ret == QMessageBox.Yes:
            if self.if_checked(test, query, val):
                msg = QMessageBox()
                msg.setIcon(QMessageBox.Information)
                msg.setText('Rezerwacja została usunięta')
                msg.setWindowTitle("Usunięto")
                msg.exec_()

                self.refresh()

    @pyqtSlot()
    def on_0_clicked(self):
        self.lbl_termin_.setTime(self.czas[0])

    @pyqtSlot()
    def on_1_clicked(self):
        self.lbl_termin_.setTime(self.czas[1])

    @pyqtSlot()
    def on_2_clicked(self):
        self.lbl_termin_.setTime(self.czas[2])

    @pyqtSlot()
    def on_3_clicked(self):
        self.lbl_termin_.setTime(self.czas[3])

    @pyqtSlot()
    def on_4_clicked(self):
        self.lbl_termin_.setTime(self.czas[4])

    @pyqtSlot()
    def on_5_clicked(self):
        self.lbl_termin_.setTime(self.czas[5])

    @pyqtSlot()
    def on_6_clicked(self):
        self.lbl_termin_.setTime(self.czas[6])

    @pyqtSlot()
    def on_7_clicked(self):
        self.lbl_termin_.setTime(self.czas[7])

    @pyqtSlot()
    def on_8_clicked(self):
        self.lbl_termin_.setTime(self.czas[8])

    @pyqtSlot()
    def on_9_clicked(self):
        self.lbl_termin_.setTime(self.czas[9])

    @pyqtSlot()
    def on_10_clicked(self):
        self.lbl_termin_.setTime(self.czas[10])

    @pyqtSlot()
    def on_11_clicked(self):
        self.lbl_termin_.setTime(self.czas[11])

    @pyqtSlot()
    def on_12_clicked(self):
        self.lbl_termin_.setTime(self.czas[12])

    @pyqtSlot()
    def on_13_clicked(self):
        self.lbl_termin_.setTime(self.czas[13])

    @pyqtSlot()
    def on_14_clicked(self):
        self.lbl_termin_.setTime(self.czas[14])

    @pyqtSlot()
    def on_15_clicked(self):
        self.lbl_termin_.setTime(self.czas[15])

    @pyqtSlot(str)
    def searching_u(self, text):
        """
        Wyszukuje po wszystkich kolumnach tabeli
        :param text:
        """
        search = QRegExp(text, Qt.CaseInsensitive, QRegExp.RegExp)
        self.proxy_u.setFilterRegExp(search)
        # Odpowiedzialne za kolumnę, po której filtruje
        self.proxy_u.setFilterKeyColumn(-1)

    @pyqtSlot(str)
    def searching_k(self, text):
        """
        Wyszukuje po wszystkich kolumnach tabeli
        :param text:
        """
        search = QRegExp(text, Qt.CaseInsensitive, QRegExp.RegExp)
        self.proxy_k.setFilterRegExp(search)
        # Odpowiedzialne za kolumnę, po której filtruje
        self.proxy_k.setFilterKeyColumn(-1)

    @pyqtSlot(str)
    def searching_p(self, text):
        """
        Wyszukuje po wszystkich kolumnach tabeli
        :param text:
        """
        search = QRegExp(text, Qt.CaseInsensitive, QRegExp.RegExp)
        self.proxy_p.setFilterRegExp(search)
        # Odpowiedzialne za kolumnę, po której filtruje
        self.proxy_p.setFilterKeyColumn(-1)
コード例 #3
0
ファイル: Stage2TCX.py プロジェクト: timmehtimmeh/StagesTCX
class Calendar(QMainWindow):
    """
    A QCalendarWidget example
    """
    def __init__(self):

        # create GUI
        QMainWindow.__init__(self)
        self.setWindowTitle('Calendar widget')
        # Set the window dimensions
        self.resize(800, 600)
        self.setMinimumSize(700, 500)

        exitAction = QAction(QIcon('exit.png'), '&Exit', self)
        exitAction.setShortcut('Ctrl+Q')
        exitAction.setStatusTip('Exit application')
        exitAction.triggered.connect(qApp.quit)

        openAction = QAction(QIcon('open.png'), '&Open', self)
        openAction.setShortcut('Ctrl+O')
        openAction.setStatusTip('Open')
        openAction.triggered.connect(self.open_chooser)

        self.statusBar()

        menubar = self.menuBar()
        fileMenu = menubar.addMenu('&File')
        fileMenu.addAction(openAction)
        fileMenu.addAction(exitAction)

        self.displayMenu = menubar.addMenu('&Display')
        pwrChecked = QAction('Power', self.displayMenu, checkable=True)
        cadChecked = QAction('Cadence', self.displayMenu, checkable=True)
        speedChecked = QAction('Speed', self.displayMenu, checkable=True)
        hrChecked = QAction('Heartrate', self.displayMenu, checkable=True)
        distanceChecked = QAction('Distance', self.displayMenu, checkable=True)

        self.displayMenu.addAction(pwrChecked)
        self.displayMenu.addAction(cadChecked)
        self.displayMenu.addAction(speedChecked)
        self.displayMenu.addAction(hrChecked)
        self.displayMenu.addAction(distanceChecked)

        pwrChecked.setChecked(True)
        cadChecked.setChecked(True)
        self.displayMenu.triggered.connect(self.updatePlot)

        # vertical layout for widgets
        vbox = QVBoxLayout()
        centralWidget = QWidget(self)
        centralWidget.setLayout(vbox)
        self.setCentralWidget(centralWidget)

        #set the central widget as a gridbox
        topLayout = QHBoxLayout()
        topWidget = QWidget(self)
        topWidget.setLayout(topLayout)

        #widget to hold calendar and time selection
        calSelLayout = QVBoxLayout()
        calSelWidget = QWidget(self)
        calSelWidget.setLayout(calSelLayout)

        # Create a calendar widget and add it to our layout
        self.cal = QCalendarWidget()
        self.cal.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)

        #calSelLayout.setAlignment(self.cal,Qt.AlignTop)

        #and create a texteditor to show the read file
        # self.textEdit = QTextEdit()
        # gridbox.addWidget(self.textEdit,0,1)

        timeSelLayout = QHBoxLayout()
        timeSelWidget = QWidget(self)
        timeSelWidget.setLayout(timeSelLayout)

        # Create the hours combobox
        self.hoursBox = QComboBox()
        self.hoursBox.addItems(
            ["12", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11"])
        self.hoursBox.setCurrentIndex(4)
        self.hoursBox.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
        timeSelLayout.addWidget(self.hoursBox)

        # Create the minutes combo box
        self.minutesBox = QComboBox()
        self.minutesBox.addItems(["00", "15", "30", "45"])
        self.minutesBox.setCurrentIndex(3)
        self.minutesBox.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
        timeSelLayout.addWidget(self.minutesBox)

        # Create the Am/Pm combo box
        self.ampmBox = QComboBox()
        self.ampmBox.addItems(["AM", "PM"])
        self.ampmBox.setCurrentIndex(1)
        self.ampmBox.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
        timeSelLayout.addWidget(self.ampmBox)

        # Create a label which we will use to show the date a week from now
        self.lbl = QLabel()
        timeSelLayout.addWidget(self.lbl)

        calSelLayout.addWidget(self.cal)
        calSelLayout.addWidget(timeSelWidget)
        calSelLayout.setAlignment(timeSelWidget, Qt.AlignTop)
        topLayout.addWidget(calSelWidget)

        bottomLayout = QHBoxLayout()
        bottomWidget = QWidget(self)
        bottomWidget.setLayout(bottomLayout)
        bottomLayout.setAlignment(Qt.AlignRight)

        # Create a process button
        self.goButton = QPushButton('Convert to TCX')
        self.goButton.setEnabled(False)
        self.goButton.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
        bottomLayout.addWidget(self.goButton)
        self.goButton.clicked.connect(self.DoWork)

        self.plotter = PlotCanvas()
        self.plotter.setSizePolicy(QSizePolicy.Expanding,
                                   QSizePolicy.Expanding)
        topLayout.addWidget(self.plotter)

        vbox.addWidget(topWidget)
        vbox.addWidget(bottomWidget)

        # Connect the clicked signal to the centre handler
        self.cal.selectionChanged.connect(self.date_changed)
        #self.connect(self.cal, QtCore.SIGNAL('selectionChanged()'), self.date_changed)
        self.outName = ''
        self.fileName = ''
        self.hours = (time.timezone if (time.localtime().tm_isdst == 0) else
                      time.altzone) / 3600
        self.minutes = 0
        self.date_changed()
        self.statusBar().showMessage('Please open csv file')
        self.show()

    def output_name(self, iname):
        # validate name ends with .CSV
        if iname.lower().endswith(".csv"):
            prefix = iname[:-3]
            oname = prefix + "tcx"
            if not os.path.exists(oname):
                return oname
            else:
                msgbox = QMessageBox()
                msgbox.setText("File %s exists, overwrite?" % oname)
                msgbox.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
                retval = msgbox.exec_()
                if retval == QMessageBox.Yes:
                    os.remove(oname)
                    return oname
                else:
                    raise Exception(
                        'File %s already exists. Cannot continue.' % oname)
        else:
            raise Exception("%s does not end with .csv" % iname)

    def getCalendarTime(self):
        offset = (time.timezone if
                  (time.localtime().tm_isdst == 0) else time.altzone) / 3600
        self.hours = int(self.hoursBox.currentText()) + int(offset)
        if (self.ampmBox.currentText() == "PM"):
            self.hours += 12
        if (self.hours >= 24):
            self.hours = self.hours - 24
        self.minutes = int(self.minutesBox.currentText())
        print(self.pydate)
        print(self.hours)
        print(self.minutes)
        print(datetime.time(self.hours, self.minutes))
        dt = datetime.datetime.combine(self.pydate,
                                       datetime.time(self.hours, self.minutes))
        return dt

    def DoWork(self):

        if self.fileName:
            try:
                self.workout.setStartTime(self.getCalendarTime())
            except:
                print("Error setting start time")
                self.statusBar().showMessage('Error setting start time')
            try:
                self.outName = self.output_name(self.fileName)
            except:
                print("Error setting output name to " + self.outName)
                self.statusBar().showMessage('Error setting output name to ' +
                                             self.outName)
            try:
                tcx_writer(self.workout).writeTCX(self.outName)
                self.statusBar().showMessage('Success writing TCX: %s' %
                                             self.outName)
                Popen_arg = r'explorer /select, "' + self.outName.replace(
                    '/', '\\') + '"'
                Popen(Popen_arg)
            except:
                print("Error creating file " + self.outName)
                self.statusBar().showMessage('Error creating file ' +
                                             self.outName)

    def date_changed(self):
        """
        Handler called when the date selection has changed
        """
        # Fetch the currently selected date, this is a QDate object
        self.date = self.cal.selectedDate()
        # This is a gives us the date contained in the QDate as a native
        # python date[time] object
        self.pydate = self.date.toPyDate()
        # Calculate the date a week from now
        # sevendays = timedelta(days=7)
        # aweeklater = self.pydate + sevendays
        # Show this date in our label
        self.lbl.setText('The selected date is: %s' % self.pydate)

    def get_date(self):
        return self.date

    def openFileNameDialog(self):
        options = QFileDialog.Options()
        options |= QFileDialog.DontUseNativeDialog
        fileName, _ = QFileDialog.getOpenFileName(
            self,
            "QFileDialog.getOpenFileName()",
            "",
            "CSV files (*.csv);;All Files (*)",
            options=options)
        if fileName:
            print(fileName)
        return fileName

    def open_chooser(self):
        self.fileName = self.openFileNameDialog()
        if self.fileName:
            self.workout = StagesWorkout(self.fileName, self.getCalendarTime())
            self.plotter.setWorkout(self.workout)
            self.goButton.setEnabled(True)
            self.statusBar().showMessage(
                'Successfully read %i stages in %s' %
                (len(self.workout.stages), self.fileName))
            self.updatePlot()

    def updatePlot(self):
        actions = []
        for action in self.displayMenu.actions():
            if action.isChecked():
                actions.append(action.text())
        print(actions)
        self.plotter.plot(actions)