Esempio n. 1
0
    def __init__(self, uredjaj=None, generatori=None, dilucije=None, parent=None, postaje=None, cfg=None, datastore=None):
        super(BASE_UMJERAVANJE, self).__init__(parent)
        self.setupUi(self)
        #MDI members ...
        self.bezNaslova = True
        self.isModified = True
        self.workingFolder = os.path.dirname(__file__)
        self.kolektor = QtGui.QWidget() #placeholder widget za kolektor preko veze
        #podaci za umjeravanje
        if datastore==None:
            self.datastore = DataStore(uredjaj=uredjaj,
                                       generatori=generatori,
                                       dilucije=dilucije,
                                       postaje=postaje,
                                       cfg=cfg)
        else:
            self.datastore = datastore

        #postavke prozora...
        self.labelUredjaj.setText(self.datastore.get_uredjaj().get_serial())
        self.labelPostaja.setText(self.datastore.get_izabranaPostaja())

        self.init_tabove()

        self.setup_connections()
Esempio n. 2
0
class Umjeravanje(BASE_UMJERAVANJE, FORM_UMJERAVANJE):
    """
    Klasa za 'child' prozor umjeravanja.
    """
    redniBroj = 1

    def __init__(self, uredjaj=None, generatori=None, dilucije=None, parent=None, postaje=None, cfg=None, datastore=None):
        super(BASE_UMJERAVANJE, self).__init__(parent)
        self.setupUi(self)
        #MDI members ...
        self.bezNaslova = True
        self.isModified = True
        self.workingFolder = os.path.dirname(__file__)
        self.kolektor = QtGui.QWidget() #placeholder widget za kolektor preko veze
        #podaci za umjeravanje
        if datastore==None:
            self.datastore = DataStore(uredjaj=uredjaj,
                                       generatori=generatori,
                                       dilucije=dilucije,
                                       postaje=postaje,
                                       cfg=cfg)
        else:
            self.datastore = datastore

        #postavke prozora...
        self.labelUredjaj.setText(self.datastore.get_uredjaj().get_serial())
        self.labelPostaja.setText(self.datastore.get_izabranaPostaja())

        self.init_tabove()

        self.setup_connections()

    def setup_connections(self):
        #update teksta postaje
        self.connect(self.tabPostavke,
                     QtCore.SIGNAL('promjena_postaje(PyQt_PyObject)'),
                     self.labelPostaja.setText)
        ### UCITAVANJE PODATAKA ###
        self.pushButtonUcitajPodatke.clicked.connect(self.read_data_from_csv)
        self.pushButtonPrikupljanjePodataka.clicked.connect(self.display_tab_kolektor)
        ### REPORT GENERATOR ###
        self.pushButtonReport.clicked.connect(self.napravi_report)
        ### RECALCULATE TRIGGERI ###
        self.connect(self.tabPostavke,
                     QtCore.SIGNAL('recalculate_all_tabs'),
                     self.recalculate_all_tabs)
        self.connect(self.tabPostavke,
                     QtCore.SIGNAL('recalculate_konverter'),
                     self.recalculate_tab_konverter)
        self.connect(self.tabPostavke,
                     QtCore.SIGNAL('recalculate_umjeravanja'),
                     self.recalculate_all_umjeravanja)
        self.connect(self.tabPostavke,
                     QtCore.SIGNAL('promjena_checkOdaziv'),
                     self.prikazi_tabove_odaziva)
        self.connect(self.tabPostavke,
                     QtCore.SIGNAL('promjena_checkKonverter'),
                     self.prikazi_tab_konverter)
        self.tableViewFrejm.clicked.connect(self.interakcija_sa_tablicom_pojedinih_mjerenja)
        ### PROMJENA AKTIVNOG TABA ###
        self.glavniTabWidget.currentChanged.connect(self.promjena_aktivnog_taba)
        ### triggeri za save check ###
        self.tabPostavke.lineEditCRMSljedivost.textChanged.connect(self.trigger_is_modified)
        self.tabPostavke.comboBoxLokacija.currentIndexChanged.connect(self.trigger_is_modified)
        self.tabPostavke.comboBoxLokacija.editTextChanged.connect(self.trigger_is_modified)
        self.tabPostavke.lineEditVrstaCRM.textChanged.connect(self.trigger_is_modified)
        self.tabPostavke.lineEditOznakaIzvjesca.textChanged.connect(self.trigger_is_modified)
        self.tabPostavke.lineEditRevizija.textChanged.connect(self.trigger_is_modified)
        self.tabPostavke.lineEditBrojObrasca.textChanged.connect(self.trigger_is_modified)
        self.tabPostavke.lineEditNorma.textChanged.connect(self.trigger_is_modified)
        self.tabPostavke.plainTextEditPuniNazivMetode.textChanged.connect(self.trigger_is_modified)
        self.tabPostavke.plainTextEditNapomena.textChanged.connect(self.trigger_is_modified)
        self.tabPostavke.lineEditDatumUmjeravanja.textChanged.connect(self.trigger_is_modified)
        self.tabPostavke.doubleSpinBoxTemperatura.valueChanged.connect(self.trigger_is_modified)
        self.tabPostavke.doubleSpinBoxVlaga.valueChanged.connect(self.trigger_is_modified)
        self.tabPostavke.doubleSpinBoxTlak.valueChanged.connect(self.trigger_is_modified)

    def scroll_na_indeks(self, indeks):
        """callback za scroll na zadani qmodel indeks"""
        try:
            self.tableViewFrejm.scrollTo(indeks)
            red = indeks.row()
            self.tableViewFrejm.selectRow(red)
        except Exception as err:
            print(str(err))
            logging.error(str(err), exc_info=True)

    def trigger_is_modified(self, x):
        """callback za promjenu stanja dokumenta"""
        self.set_modified(True)

    def napravi_report(self):
        """
        Izrada PDF reporta umjeravanja.
        """
        komponente = self.datastore.get_uredjaj().get_listu_komponenti()
        if self.datastore.isNOx:
            plin = 'NO'
        elif len(komponente) > 1:
            plin, ok = QtGui.QInputDialog.getItem(self,
                                                  'Izbor komponente za report',
                                                  'Komponenta :',
                                                  komponente,
                                                  editable=False)
            if not ok:
                return None
        else:
            plin = komponente[0]
        ime = QtGui.QFileDialog.getSaveFileName(parent=self,
                                                caption='Spremi pdf report',
                                                filter = 'pdf file (*.pdf)')
        if ime:
            report = ReportGenerator()
            try:
                report.generiraj_report(ime, plin, self)
            except Exception as err:
                logging.error(str(err), exc_info=True)
                msg = "\n".join(['Izvještaj nije uspješno generiran.', str(err)])
                QtGui.QMessageBox.information(self, 'Problem', msg)

    def get_koristene_serial_portove(self):
        """
        Metoda vraca listu koristenih serial portova u aplikaciji. Metoda zanemaruje
        trenutno koristeni port u umjeravanju.
        """
        setPortova = self.parent().parent().parent().parent().parent().get_aktivne_serial_portove()
        setPortova.discard(None)
        #moram omoguciti izbor istog seriala koji je koristen u umjeravanju
        trenutni = self.get_serial_kolektora()
        setPortova.discard(trenutni)
        return list(setPortova)

    def get_serial_kolektora(self):
        """
        Metoda dohvaca koristeni serial port u kolektoru.
        """
        try:
            return self.kolektor.get_used_serial()
        except Exception as err:
            logging.error(str(err), exc_info=True)
            return None

    def display_tab_kolektor(self, x):
        """
        Callback gumba za prikaz atba kolektor. Ulazni parametar je boolean (stanje gumba).
        Ako je x True:
        -stvori objekt kolektor
        -dodaj ga u tab widget i spoji signale
        Ako je x False:
        -zatvori objekt kolektor
        -izbrisi objekt kolektor
        """
        if x:
            uredjaj = self.datastore.get_uredjaj()
            konfig = self.datastore.get_konfig()
            #koristeni serial portovi?
            self.kolektor = Kolektor(uredjaj=uredjaj, konfig=konfig, parent=self, datastore=self.datastore)
            #connect signal i slot
            self.connect(self.kolektor,
                         QtCore.SIGNAL('spremi_preuzete_podatke(PyQt_PyObject)'),
                         self.aktiviraj_ucitane_podatke)
            self.connect(self.kolektor,
                         QtCore.SIGNAL('update_table_view'),
                         self.tableViewFrejm.update)
            self.glavniTabWidget.addTab(self.kolektor, 'Kolektor')
        else:
            msg = 'Ako ugasite tab za skupljanje podataka, izgubiti cete sve podatke koji nisu spremljeni. Da li zelite ugasiti kolektor?'
            title = 'Potvrdi gasenje kolektora'
            chk = QtGui.QMessageBox.question(self, title, msg, QtGui.QMessageBox.Ok | QtGui.QMessageBox.No)
            if chk == QtGui.QMessageBox.Ok:
                ind = self.glavniTabWidget.indexOf(self.kolektor)
                self.glavniTabWidget.removeTab(ind)
                self.kolektor.close()
                self.kolektor = QtGui.QWidget()
            else:
                self.pushButtonPrikupljanjePodataka.blockSignals(True)
                self.pushButtonPrikupljanjePodataka.toggle()
                self.pushButtonPrikupljanjePodataka.blockSignals(False)

    def tab_isValid(self, tabname):
        """helper metoda za provjeru da li je zadano mjerenje validno"""
        if tabname != None and tabname in self.dictTabova:
            return True
        else:
            return False

    def prikazi_tab_konverter(self):
        check = self.datastore.get_checkKonverter()
        if 'konverter' in self.dictTabova:
            if check:
                self.glavniTabWidget.addTab(self.dictTabova['konverter'], 'konverter')
            else:
                ind = self.glavniTabWidget.indexOf(self.dictTabova['konverter'])
                self.glavniTabWidget.removeTab(ind)

    def prikazi_tabove_odaziva(self):
        """toggle tabova odaziv..."""
        check = self.datastore.get_checkOdaziv()
        if check:
            for tab in self.dictTabova:
                if tab.endswith('-odaziv'):
                    self.glavniTabWidget.addTab(self.dictTabova[tab], tab)
        else:
            for tab in self.dictTabova:
                if tab.endswith('-odaziv'):
                    ind = self.glavniTabWidget.indexOf(self.dictTabova[tab])
                    self.glavniTabWidget.removeTab(ind)

    def recalculate_all_umjeravanja(self):
        """recalculate sve tabove umjeravanja"""
        print('RECALCULATE ALL UMJERAVANJA')
        for tab in self.dictTabova:
            if not tab.endswith('-odaziv') and tab != 'konverter':
                self.recalculate_tab(tabname=tab)

    def recalculate_all_tabs(self):
        """recalculate sve tabove"""
        print('RECALCULATE ALL')
        for tab in self.dictTabova:
            self.recalculate_tab(tabname=tab)

    def recalculate_tab_konverter(self):
        print('RECALCULATE KONVERTER')
        self.recalculate_tab(tabname='konverter')

    @pomocni.activate_wait_spinner
    def recalculate_tab(self, tabname=None):
        """recalculate pojedinacni tab"""
        self.set_modified(True)
        try:
            if self.tab_isValid(tabname):
                print('recalculating --> {0}'.format(tabname))
                if tabname == 'konverter':
                    tocke = self.datastore.tabData[tabname].get_tocke()
                    opseg = self.datastore.get_izabraniOpseg()
                    cnox50 = self.datastore.get_cNOx50()
                    cnox95 = self.datastore.get_cNOx95()
                    ecmin = self.datastore.get_uredjaj().get_analitickaMetoda().get_Ec_min()
                    ecmax = self.datastore.get_uredjaj().get_analitickaMetoda().get_Ec_max()
                    frejm = self.datastore.tabData[tabname].get_frejm()
                    if not isinstance(frejm, pd.core.frame.DataFrame):
                        #nije zadan dataframe
                        return None
                    mapa = kalkulator.racunaj_vrijednosti_provjere_konvertera(tocke=tocke,
                                                                              opseg=opseg,
                                                                              frejm=frejm,
                                                                              cnox50=cnox50,
                                                                              cnox95=cnox95,
                                                                              ecmin=ecmin,
                                                                              ecmax=ecmax)
                    self.dictTabova[tabname].update_rezultat(mapa)
                    self.datastore.tabData[tabname].set_rezultat(mapa)
                elif tabname.endswith('-odaziv'):
                    self.dictTabova[tabname].update_rezultate()
                else:
                    tocke = self.datastore.tabData[tabname].get_tocke()
                    linearnost = self.datastore.get_checkLinearnost()
                    ponovljivost = self.datastore.get_checkPonovljivost()
                    opseg = self.datastore.get_izabraniOpseg()
                    cCRM = self.datastore.get_koncentracijaCRM()
                    sCRM = self.datastore.get_UCRM()
                    #dilucija
                    key = self.datastore.get_izabranaDilucija()
                    dilucija = self.datastore.get_objekt_izabrane_dilucije(key)
                    uNul = dilucija.get_uNul()
                    uKal = dilucija.get_uKal()
                    #data
                    frejm = self.datastore.tabData[tabname].get_frejm()
                    if isinstance(frejm, pd.core.frame.DataFrame):
                        data = list(frejm[tabname])
                    else:
                        #nije zadan dataframe
                        return None
                    #generator cistog zraka
                    key = self.datastore.get_izabraniGenerator()
                    generator = self.datastore.get_objekt_izabranog_generatora(key)
                    if tabname == 'SO2':
                        plinMaxC = generator.get_maxSO2()
                    elif tabname in ['NOx', 'NO', 'NO2']:
                        plinMaxC = generator.get_maxNOx()
                    elif tabname == 'CO':
                        plinMaxC = generator.get_maxCO()
                    elif tabname == 'O3':
                        plinMaxC = generator.get_maxO3()
                    else:
                        plinMaxC = generator.get_maxBTX()
                    #metoda
                    metoda = self.datastore.get_uredjaj().get_analitickaMetoda()
                    jedinica = metoda.get_jedinica()
                    srzlimit = metoda.get_Srz()
                    srslimit = metoda.get_Srs()
                    rzlimit = metoda.get_rz()
                    rmaxlimit = metoda.get_rmax()
                    mapa = kalkulator.racun_umjeravanja(tocke=tocke,
                                                        data=data,
                                                        linearnost=linearnost,
                                                        opseg=opseg,
                                                        cCRM=cCRM,
                                                        sCRM=sCRM,
                                                        uNul=uNul,
                                                        uKal=uKal,
                                                        plinMaxC=plinMaxC,
                                                        ponovljivost=ponovljivost,
                                                        jedinica=jedinica,
                                                        srzlimit=srzlimit,
                                                        srslimit=srslimit,
                                                        rzlimit=rzlimit,
                                                        rmaxlimit=rmaxlimit)
                    self.dictTabova[tabname].update_rezultat(mapa)
                    self.datastore.tabData[tabname].set_rezultat(mapa)
            else:
                msg = 'recalculate nepostojeceg taba {0}'.format(str(tabname))
                logging.warning(msg)
        except Exception as err:
            logging.error(str(err), exc_info=True)

    def aktiviraj_ucitane_podatke(self, mapa):
        """
        Spremanje podataka iz prozora u neku instancu otvorenog umjeravanja ili otvaranje novog umjeravanja..
        kljucevi mape su:
        'podaci':sekundniFrejm
        'minutniPodaci':minutniFrejm
        'uredjaj':serijski broj uredjaja
        """
        minutni = mapa['minutniPodaci']
        sekundni = mapa['podaci']
        for tab in self.dictTabova:
            if tab.endswith('-odaziv'):
                #prebaci sekundni frejm sa rise i fall podacima za tab u datastore
                model = self.dictTabova[tab].get_model()
                komponenta = self.dictTabova[tab].naziv
                model.set_slajs(sekundni[komponenta], komponenta)
                self.datastore.tabData[tab].set_frejm(model.get_frejm())
                self.recalculate_tab(tabname=tab)
            else:
                #prebaci minutni frejm u datastore
                self.datastore.tabData[tab].set_frejm(minutni)
                #updejtaj qt model u tab widgetu
                model = self.dictTabova[tab].get_model()
                model.set_frejm(minutni)
                self.recalculate_tab(tabname=tab)

    def read_data_from_csv(self):
        """
        Ucitavanje sirovih podataka iz csv filea putem wizarda.

        redosljed ucitavanja je bitan:
        1. clear tabove (ako su razliciti od postojecih tabova)
        2. update dokument sa novim podacima
        3. create tabove (ako su prethodno izbrisani)
        """
        fileWizard = read_file_wizard.CarobnjakZaCitanjeFilea(datastore=self.datastore)
        ok = fileWizard.exec_()
        if ok:
            frejmovi = fileWizard.get_frejmovi()
            minutni = frejmovi['minutni'] #za tab umjeravanja i konverter
            sekundni = frejmovi['sekundni'] #za tab odaziva
            for tab in self.dictTabova:
                if tab.endswith('-odaziv'):
                    #prebaci sekundni frejm sa rise i fall podacima za tab u datastore
                    model = self.dictTabova[tab].get_model()
                    komponenta = self.dictTabova[tab].naziv
                    model.set_slajs(sekundni[komponenta], komponenta)
                    self.datastore.tabData[tab].set_frejm(model.get_frejm())
                    self.recalculate_tab(tabname=tab)
                else:
                    #prebaci minutni frejm u datastore
                    self.datastore.tabData[tab].set_frejm(minutni)
                    #updejtaj qt model u tab widgetu
                    model = self.dictTabova[tab].get_model()
                    model.set_frejm(minutni)
                    self.recalculate_tab(tabname=tab)

    def interakcija_sa_tablicom_pojedinih_mjerenja(self, indeks):
        """interakcija sa tablicom sa podacima"""
        try:
            widg = self.glavniTabWidget.currentWidget()
            mjerenje = widg.plin
            x = indeks.row()
            if mjerenje == 'postavke':
                pass
            elif mjerenje.endswith('-odaziv'):
                #delegiraj klik widgetu
                widg.update_rezultate()
            elif mjerenje == 'konverter':
                model = self.dictTabova[mjerenje].get_model()
                model.set_start(x)
                self.datastore.tabData[mjerenje].set_startIndeks(x)
                self.recalculate_tab(tabname=mjerenje)
            else:
                if self.datastore.isNOx:
                    model = self.dictTabova['NO'].get_model()
                    model.set_start(x)
                    self.datastore.tabData['NO'].set_startIndeks(x)
                    self.recalculate_tab(tabname='NO')
                    model = self.dictTabova['NOx'].get_model()
                    model.set_start(x)
                    self.datastore.tabData['NOx'].set_startIndeks(x)
                    self.recalculate_tab(tabname='NOx')
                else:
                    model = self.dictTabova[mjerenje].get_model()
                    model.set_start(x)
                    self.datastore.tabData[mjerenje].set_startIndeks(x)
                    self.recalculate_tab(tabname=mjerenje)
        except Exception as err:
            logging.error(str(err), exc_info=True)

    def promjena_aktivnog_taba(self, x):
        """metoda zaduzena za promjenu konteksta prilikom promjene taba. Definira
        koji je model aktivan u ljevoj tablici sa podacima."""
        try:
            nazivTaba = self.glavniTabWidget.currentWidget().plin
            if nazivTaba == 'Postavke':
                emptyModel = SiroviFrameModel(frejm=pd.DataFrame(),
                                              tocke=self.datastore.init_tockeUmjeravanja(),
                                              start=0)
                self.tableViewFrejm.setModel(emptyModel)
                self.tableViewFrejm.update()
                #exit from method
                return None
            elif nazivTaba == 'kolektor':
                model = self.kolektor.get_model()
                self.tableViewFrejm.setModel(model)
                self.tableViewFrejm.update()
            else:
                model = self.dictTabova[nazivTaba].get_model()
                self.tableViewFrejm.setModel(model)
                self.tableViewFrejm.update()

            #display stupaca u modelu
            if nazivTaba.endswith('-odaziv'):
                self.glavniTabWidget.currentWidget().update_rezultate()
                self.tableViewFrejm.resizeColumnToContents(0)
                self.tableViewFrejm.resizeColumnToContents(1)
                self.tableViewFrejm.horizontalHeader().setStretchLastSection(True)
            else:
                self.tableViewFrejm.horizontalHeader().setResizeMode(QtGui.QHeaderView.Stretch)
            self.tableViewFrejm.update()
        except Exception as err:
            logging.error(str(err), exc_info=True)
################################################################################
    #metode za rad i prikaz umjeravanja
    def init_tabove(self):
        """
        stvaranje tabova i povezivanje istih...
        """
        self.dictTabova = {}
        #tab postavke
        self.tabPostavke = tab_postavke.TabPostavke(datastore=self.datastore)
        self.glavniTabWidget.addTab(self.tabPostavke, 'Postavke')
        #ostali tabovi:
        for tab in self.datastore.tabData.keys():
            if tab.endswith('-odaziv'):
                self.dictTabova[tab] = tab_odaziv.TabOdaziv(datastore=self.datastore, plin=tab)
                ### scroll podataka tab odaziv...###
                self.connect(self.dictTabova[tab],
                             QtCore.SIGNAL('scroll_to_index(PyQt_PyObject)'),
                             self.scroll_na_indeks)
                if self.datastore.get_checkOdaziv():
                    self.glavniTabWidget.addTab(self.dictTabova[tab], tab)
            elif tab == 'konverter':
                self.dictTabova[tab] = tab_konverter.TabKonverter(datastore=self.datastore, plin=tab)
                if self.datastore.get_checkKonverter():
                    self.glavniTabWidget.addTab(self.dictTabova[tab], tab)
            else:
                self.dictTabova[tab] = tab_rezultat.TabRezultat(datastore=self.datastore, plin=tab)
                self.glavniTabWidget.addTab(self.dictTabova[tab], tab)
                #connectioni za dodavanje, brisanje i editiranje tocaka pojedinog taba
                self.connect(self.dictTabova[tab],
                             QtCore.SIGNAL('panel_dodaj_umjernu_tocku'),
                             self.dodaj_umjernu_tocku)
                self.connect(self.dictTabova[tab],
                             QtCore.SIGNAL('panel_makni_umjernu_tocku(PyQt_PyObject)'),
                             self.makni_umjernu_tocku)
                self.connect(self.dictTabova[tab],
                             QtCore.SIGNAL('panel_edit_umjernu_tocku(PyQt_PyObject)'),
                             self.edit_umjernu_tocku)

    def dodaj_umjernu_tocku(self):
        """
        Metoda dodaje tocku na popis tocaka za mjerenje(tab). Dodaje je iza vec
        definiranih tocaka, ukupno 30 indeksa, prvih 15 zanemarenih, random boja.
        """
        try:
            tabname = self.glavniTabWidget.currentWidget().plin
            frejm = self.datastore.tabData[tabname].get_frejm()
            if isinstance(frejm, pd.core.frame.DataFrame):
                tocke = copy.deepcopy(self.datastore.tabData[tabname].get_tocke())
                ime = "".join(['TOCKA',str(len(tocke)+1)])
                indeks =  max([max(tocka.indeksi) for tocka in tocke])
                start = indeks+15
                end = start+15
                cref = 0.0
                novaTocka = Tocka(ime=ime, start=start, end=end, cref=cref)
                tocke.append(novaTocka)
                self.datastore.tabData[tabname].set_tocke(tocke)
                self.recalculate_tab(tabname=tabname)
        except Exception as err:
            logging.error(str(err), exc_info=True)

    def makni_umjernu_tocku(self, red):
        """
        Metoda brise tocku zadanu indeksom (red) sa popisa tocaka za mjerenje.
        Metoda mjenja nazive ostalih tocaka radi konzistencije.
        """
        try:
            tabname = self.glavniTabWidget.currentWidget().plin
            frejm = self.datastore.tabData[tabname].get_frejm()
            if isinstance(frejm, pd.core.frame.DataFrame):
                tocke = copy.deepcopy(self.datastore.tabData[tabname].get_tocke())
                tocke.pop(red)
                #rename ostale tocke
                for i in range(len(tocke)):
                    tocke[i].ime = "".join(['TOCKA',str(i+1)])
                self.datastore.tabData[tabname].set_tocke(tocke)
                self.recalculate_tab(tabname=tabname)
        except Exception as err:
            logging.error(str(err), exc_info=True)

    def edit_umjernu_tocku(self, red):
        """
        Edit umjerne tocke. Poziva se dijalog za edit parametara.
        Ulazni parametar (red) je indeks pod kojim se ta tocka nalazi
        u listi tocaka.
        """
        try:
            tabname = self.glavniTabWidget.currentWidget().plin
            tocke = copy.deepcopy(self.datastore.tabData[tabname].get_tocke())
            start = self.datastore.tabData[tabname].get_startIndeks()
            frejm = self.datastore.tabData[tabname].get_frejm()
            if isinstance(frejm, pd.core.frame.DataFrame):
                staraTocka = tocke[red]
                if staraTocka.crefFaktor == 0.0:
                    staraTockaIsZero = True
                else:
                    staraTockaIsZero = False
                brojZeroTocaka = len([i for i in tocke if i.crefFaktor == 0.0])
                #poziv dijaloga za edit
                dijalog = dijalog_edit_tocke.EditTockuDijalog(frejm=frejm,
                                                              tocke=tocke,
                                                              start=start,
                                                              indeks=red,
                                                              parent=self)
                if dijalog.exec_():
                    novaTocka = dijalog.get_promjenjena_tocka()
                    if staraTockaIsZero and brojZeroTocaka == 1:
                        if novaTocka.crefFaktor == 0.0:
                            tocke[red] = novaTocka
                            self.datastore.tabData[tabname].set_tocke(tocke)
                            self.recalculate_tab(tabname=tabname)
                        else:
                            QtGui.QMessageBox.information(self, 'Oprez','Mora postojati barem jedna zero tocka. Cref faktor tocke nije promjenjen.')
                            novaTocka.crefFaktor = 0.0
                            tocke[red] = novaTocka
                            self.datastore.tabData[tabname].set_tocke(tocke)
                            self.recalculate_tab(tabname=tabname)
                    else:
                        tocke[red] = novaTocka
                        self.datastore.tabData[tabname].set_tocke(tocke)
                        self.recalculate_tab(tabname=tabname)
        except Exception as err:
            logging.error(str(err), exc_info=True)
################################################################################
    #metode za MDI interface
    def novi_file(self, folder=None):
        """inicijalizacija novog filea umjeravanja"""
        self.bezNaslova = True
        if folder:
            if os.path.isdir(folder):
                self.workingFolder = folder
        selectedFilter = "Umjeravanja (*.kal)"
        path = QtGui.QFileDialog.getSaveFileName(self, 'Save as', self.workingFolder, selectedFilter)
        if path:
            fullpath = os.path.normpath(path)
        else:
            #path nije zadan, koristi default
            vrijeme = datetime.datetime.now().strftime('%Y-%m-%d_%H-%M-%S')
            naziv = 'dokument{0}_{1}.kal'.format(str(Umjeravanje.redniBroj), vrijeme)
            Umjeravanje.redniBroj += 1
            fullpath = os.path.join(self.workingFolder, naziv)
            fullpath = os.path.normpath(fullpath) #normalizacija
        self.set_trenutnoImeFilea(fullpath)
        self.set_modified(True)

    def set_modified(self, x):
        """setter cheka za stanje promjene dokumenta"""
        self.isModified = x
        if x:
            title = " ".join([self.trenutnoImeFilea, '(*)'])
        else:
            title = self.trenutnoImeFilea
        self.setWindowTitle(title)

    def get_modified(self):
        """getter cheka za stanje promjene dokumenta"""
        return self.isModified

    def set_trenutnoImeFilea(self, path):
        """setter patha do filea"""
        self.trenutnoImeFilea = path
        self.bezNaslova = False

    def get_trenutnoImeFilea(self):
        """getter patha do filea"""
        return self.trenutnoImeFilea

    def load_file(self, path=None):
        """load podataka iz spremljenog filea u objekt"""
        QtGui.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor)
        try:
            if path==None:
                return False
            self.set_full_path_filea(path)
            self.recalculate_all_tabs()
            QtGui.QApplication.restoreOverrideCursor()
            logging.info('Umjeravanje {0} loaded'.format(path))
            return True
        except Exception as err:
            logging.error(str(err), exc_info=True)
            QtGui.QApplication.restoreOverrideCursor()
            return False

    def save(self):
        """save podatke u file"""
        if self.bezNaslova:
            return self.save_file_as()
        else:
            return self.save_file(self.trenutnoImeFilea)

    def save_file_as(self):
        """save file bez naslova... otvori dijalog za izbor naziva"""
        selectedFilter = "Umjeravanja (*.kal)"
        path = QtGui.QFileDialog.getSaveFileName(self, 'Save as', self.trenutnoImeFilea, selectedFilter)
        if not path:
            return False
        if not path.endswith('.kal'):
            path = "".join([path, '.kal'])
        return self.save_file(path)

    def save_file(self, path):
        """funkcija za spremanje stanja umjeravanja u file"""
        QtGui.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor)
        try:
            with open(path, 'wb') as the_file:
                #pickle datastore
                data = self.datastore.serialize()
                the_file.write(data)
            self.set_full_path_filea(path)
            QtGui.QApplication.restoreOverrideCursor()
            logging.info('Umjeravanje {0} saved'.format(path))
            return True
        except Exception as err:
            logging.error(str(err), exc_info=True)
            QtGui.QApplication.restoreOverrideCursor()
            QtGui.QMessageBox.warning(self, 'Problem', 'Umjeravanje nije uspjesno spremljeno.\n{0}'.format(str(err)))
            return False

    def get_filename_from_path(self):
        """funkcija vraca samo naziv trenunog imena filea (bez foldera)"""
        x = os.path.split(self.trenutnoImeFilea)
        return x[1]

    def closeEvent(self, event):
        if self.provjeri_status_prije_izlaza():
            #propisno ugasi kolektor
            self.kolektor.close()
            self.kolektor = QtGui.QWidget()
            event.accept()
        else:
            event.ignore()

    def provjeri_status_prije_izlaza(self):
        """metoda provjerava da li su promjene spremljene prije gasenja prozora"""
        if self.get_modified():
            msg = 'Promjene na trenutnom umjeravanju nisu spremljene. Da li zelite spremiti promjene?'
            response = QtGui.QMessageBox.warning(self,
                                                 'Upozorenje',
                                                 msg,
                                                 QtGui.QMessageBox.Save | QtGui.QMessageBox.Discard | QtGui.QMessageBox.Cancel)
            if response == QtGui.QMessageBox.Save:
                return self.save()
            elif response == QtGui.QMessageBox.Cancel:
                return False
        return True

    def set_full_path_filea(self, path):
        """metoda postavlja path do filea u objekt. Te mjenja naziv prozora i
        status 'spremljenosti' (koristi se prilikom spremanja i loada filea)"""
        self.set_trenutnoImeFilea(path)
        self.set_modified(False)