Example #1
0
    def __init__(self, parent=None):
        super(MaeBird, self).__init__(parent)
        
        self.models = ModelFactory()

        self.table = None
        self.languages = {'perimary': 'Fin', 'secondary': 'Eng', 
                         'tertiary': 'Swe'}
        
        self.dbtype = __DB__
        self.dbfile = None
        self.db = None
        
        self.matches = []
        self.currentsearchitem = 0
        
        self.fullscreen = False
        self.setupUi(self)
        
        self.setWindowTitle(__APPNAME__ + ' ' + __VERSION__)
        
        # TODO: loading settings should be moved to a separate method
        settings = QSettings()
        
        # Set up logging
        loggingdir = settings.value("Logging/loggingDir")
        if loggingdir is None:
            loggingdir = __USER_DATA_DIR__
        self.logger = Logger('root', loggingdir=loggingdir)
        if settings.value("Settings/debugging"):
            self.logger.debugging = int(settings.value("Settings/debugging"))
            self.logger.debug('Logging initialized')
        
        # Try to load previous session
        if settings.value("Settings/saveSettings"):
            self.saveSettings = int(settings.value("Settings/saveSettings"))
        else:
            self.saveSettings = 1
                      
        if self.saveSettings:
            QTimer.singleShot(0, self.load_initial_data)
            #QTimer.singleShot(0, self.load_initial_model)
        
        self.header = self.tableView.horizontalHeader()
        self.header.sectionDoubleClicked.connect(self.sort_table)
        
        self.search.textEdited.connect(self.update_ui)
        self.search.setFocus()
        self.searchNextButton.clicked.connect(self.update_ui)
        self.searchPrevButton.clicked.connect(self.update_ui)
        
        self.tableView.pressed.connect(self.update_ui)
        
        self.tableView.doubleClicked.connect(
                    lambda: self.handle_observation(ObservationDialog.SHOW))
        self.addButton.clicked.connect(
                    lambda: self.handle_observation(ObservationDialog.ADD))
        self.deleteButton.clicked.connect(
                    lambda: self.handle_observation(ObservationDialog.DELETE))
Example #2
0
class ObservationDialog(QDialog, Ui_observationDialog):
    
    ''' A dialog delegate that handles the displaying of the observation model
    in a suitable GUI dialog.
    '''
    
    FIRST, PREV, NEXT, LAST, CURRENT = range(5)
    ADD, DELETE, SHOW = range(3)
    
    def __init__(self, model, index, parent=None):
        super(ObservationDialog, self).__init__(parent)
        
        self.logger = Logger('root.observationDialog')
        self.logger.debug('Debug set to: %s' % str(parent.logger.debugging))
        
        self.setupUi(self)
#        self.dateTimeEdit.setDateTime(QDateTime.currentDateTime())
        
        # An observation model is passed to the constructor as a parameter
        self.model = model
        
        # Build a QCompleter that is based on a species model's species name.
        # This way user can start typing the name in a line edit and the 
        # completion will suggest suitable species names based on the model
        
        # TODO: language for the species name completion needs to be handled
        # TODO: both completers have model column indexes hard coded in, thus
        # they will break if the model is modified
        sppCompleter = QCompleter(self)
        sppCompleter.setModel(self.model.data_model)
        sppCompleter.setCompletionColumn(4)
        sppCompleter.setCompletionMode(QCompleter.InlineCompletion)
        sppCompleter.setCaseSensitivity(Qt.CaseInsensitive)
        self.sppLineEdit.setCompleter(sppCompleter)
        
        # Build a QCompleter that is based on a species model's abbreviation.
        # This way user can start typing the abbreviation in a line edit and the 
        # completion will suggest suitable species names based on the model
        abbrCompleter = QCompleter(self)
        abbrCompleter.setModel(self.model.data_model)
        abbrCompleter.setCompletionColumn(1)
        abbrCompleter.setCompletionMode(QCompleter.InlineCompletion)
        self.abbrLineEdit.setCompleter(abbrCompleter)
        
        # The underlying (observation) model is automatically updated through 
        # a QDataWidgetMapper
        self.mapper = QDataWidgetMapper(self)
        self.mapper.setSubmitPolicy(QDataWidgetMapper.ManualSubmit)
        self.mapper.setModel(model)
        # ID is mapped to a disabled dummy label in order to include it in the
        # WidgetMapper --> not very elegant
        self.mapper.addMapping(self.idLineEdit, model.ID)
        self.mapper.addMapping(self.sppLineEdit, model.SPECIES)
        self.mapper.addMapping(self.abbrLineEdit, model.ABBR)
        self.mapper.addMapping(self.countSpinBox, model.COUNT)
        self.mapper.addMapping(self.dateTimeEdit, model.TIME)
        self.mapper.addMapping(self.locLineEdit, model.LOCATION)
        self.mapper.addMapping(self.notesTextEdit, model.NOTES)
        self.mapper.setCurrentModelIndex(index)
        
        self.firstButton.clicked.connect(
                            lambda: self.saveRecord(ObservationDialog.FIRST))
        self.prevButton.clicked.connect(
                            lambda: self.saveRecord(ObservationDialog.PREV))
        self.nextButton.clicked.connect(
                            lambda: self.saveRecord(ObservationDialog.NEXT))
        self.lastButton.clicked.connect(
                            lambda: self.saveRecord(ObservationDialog.LAST))
        self.saveButton.clicked.connect(
                            lambda: self.saveRecord(ObservationDialog.CURRENT))
        self.closeButton.clicked.connect(self.reject)
        
        self.sppLineEdit.editingFinished.connect(self.update_fields)
        
    def addRecord(self):
        row = self.model.rowCount()
        self.model.insertRow(row)
        
        now = QDateTime.currentDateTime()
        self.dateTimeEdit.setDateTime(now)
        self.sppLineEdit.setFocus()
        self.mapper.setCurrentIndex(row)

    def deleteRecord(self):
        species = self.sppLineEdit.text()
        obstime = self.dateTimeEdit.dateTime().toString(
                                            DATETIME_FORMAT)
        if (QMessageBox.question(self,
                "Delete",
                "Delete observation of <br>%s on %s?" % (species, obstime),
                QMessageBox.Yes|QMessageBox.No) ==
                QMessageBox.No):
            return
        row = self.mapper.currentIndex()
        self.model.removeRow(row)
        self.model.submitAll()
        if row + 1 >= self.model.rowCount():
            row = self.model.rowCount() - 1
        self.mapper.setCurrentIndex(row)
        
    def reject(self):
        QDialog.reject(self)

    def accept(self):
        self.mapper.submit()
        QDialog.accept(self)
    
    def saveRecord(self, where):
        ''' Method saves the current row in the self.mapper and moves the 
        data model cursor to a given location.
        '''
        
        if self.sppLineEdit.text() == "":
            QMessageBox.warning(self, "Warning",
                "You must enter a species name!", QMessageBox.Ok)
            return
        
        # Get the current index and submit changes to the underlying model
        row = self.mapper.currentIndex()
        self.mapper.submit()
        
        # Move the data model cursor to a given location
        if where == ObservationDialog.FIRST:
            row = 0
        elif where == ObservationDialog.PREV:
            row = 0 if row <= 1 else row - 1
        elif where == ObservationDialog.NEXT:
            row += 1
            if row >= self.model.rowCount():
                row = self.model.rowCount() - 1
        elif where == ObservationDialog.LAST:
            row = self.model.rowCount() - 1
        self.mapper.setCurrentIndex(row)

    def update_fields(self):
        '''Called when editing of the sppLineEdit stops, etc. species name input
        is complete. Species name will be searched from the model and 
        corresponding abbreviation string and ID number will be set.'''
        item = self.sppLineEdit.text()
        item = item.capitalize()
        # Match the user entered name to an abbreviation in the species model        
        matches =  self.model.data_model.match(self.model.data_model.index(0, 4),
                                               Qt.DisplayRole,
                                               item,
                                               hits=1,
                                               flags=Qt.MatchExactly)
        if matches:
            # There should be only one match
            match_row = matches[0].row()
            abbreviation = self.model.data_model.index(match_row, 
                                            self.model.data_model.ABBR).data()
            # Also get the ID for updating the model
            id = self.model.data_model.index(match_row, 
                                            self.model.data_model.ID).data()
            self.abbrLineEdit.setText(abbreviation)
Example #3
0
    def __init__(self, model, index, parent=None):
        super(ObservationDialog, self).__init__(parent)
        
        self.logger = Logger('root.observationDialog')
        self.logger.debug('Debug set to: %s' % str(parent.logger.debugging))
        
        self.setupUi(self)
#        self.dateTimeEdit.setDateTime(QDateTime.currentDateTime())
        
        # An observation model is passed to the constructor as a parameter
        self.model = model
        
        # Build a QCompleter that is based on a species model's species name.
        # This way user can start typing the name in a line edit and the 
        # completion will suggest suitable species names based on the model
        
        # TODO: language for the species name completion needs to be handled
        # TODO: both completers have model column indexes hard coded in, thus
        # they will break if the model is modified
        sppCompleter = QCompleter(self)
        sppCompleter.setModel(self.model.data_model)
        sppCompleter.setCompletionColumn(4)
        sppCompleter.setCompletionMode(QCompleter.InlineCompletion)
        sppCompleter.setCaseSensitivity(Qt.CaseInsensitive)
        self.sppLineEdit.setCompleter(sppCompleter)
        
        # Build a QCompleter that is based on a species model's abbreviation.
        # This way user can start typing the abbreviation in a line edit and the 
        # completion will suggest suitable species names based on the model
        abbrCompleter = QCompleter(self)
        abbrCompleter.setModel(self.model.data_model)
        abbrCompleter.setCompletionColumn(1)
        abbrCompleter.setCompletionMode(QCompleter.InlineCompletion)
        self.abbrLineEdit.setCompleter(abbrCompleter)
        
        # The underlying (observation) model is automatically updated through 
        # a QDataWidgetMapper
        self.mapper = QDataWidgetMapper(self)
        self.mapper.setSubmitPolicy(QDataWidgetMapper.ManualSubmit)
        self.mapper.setModel(model)
        # ID is mapped to a disabled dummy label in order to include it in the
        # WidgetMapper --> not very elegant
        self.mapper.addMapping(self.idLineEdit, model.ID)
        self.mapper.addMapping(self.sppLineEdit, model.SPECIES)
        self.mapper.addMapping(self.abbrLineEdit, model.ABBR)
        self.mapper.addMapping(self.countSpinBox, model.COUNT)
        self.mapper.addMapping(self.dateTimeEdit, model.TIME)
        self.mapper.addMapping(self.locLineEdit, model.LOCATION)
        self.mapper.addMapping(self.notesTextEdit, model.NOTES)
        self.mapper.setCurrentModelIndex(index)
        
        self.firstButton.clicked.connect(
                            lambda: self.saveRecord(ObservationDialog.FIRST))
        self.prevButton.clicked.connect(
                            lambda: self.saveRecord(ObservationDialog.PREV))
        self.nextButton.clicked.connect(
                            lambda: self.saveRecord(ObservationDialog.NEXT))
        self.lastButton.clicked.connect(
                            lambda: self.saveRecord(ObservationDialog.LAST))
        self.saveButton.clicked.connect(
                            lambda: self.saveRecord(ObservationDialog.CURRENT))
        self.closeButton.clicked.connect(self.reject)
        
        self.sppLineEdit.editingFinished.connect(self.update_fields)
Example #4
0
class MaeBird(QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(MaeBird, self).__init__(parent)
        
        self.models = ModelFactory()

        self.table = None
        self.languages = {'perimary': 'Fin', 'secondary': 'Eng', 
                         'tertiary': 'Swe'}
        
        self.dbtype = __DB__
        self.dbfile = None
        self.db = None
        
        self.matches = []
        self.currentsearchitem = 0
        
        self.fullscreen = False
        self.setupUi(self)
        
        self.setWindowTitle(__APPNAME__ + ' ' + __VERSION__)
        
        # TODO: loading settings should be moved to a separate method
        settings = QSettings()
        
        # Set up logging
        loggingdir = settings.value("Logging/loggingDir")
        if loggingdir is None:
            loggingdir = __USER_DATA_DIR__
        self.logger = Logger('root', loggingdir=loggingdir)
        if settings.value("Settings/debugging"):
            self.logger.debugging = int(settings.value("Settings/debugging"))
            self.logger.debug('Logging initialized')
        
        # Try to load previous session
        if settings.value("Settings/saveSettings"):
            self.saveSettings = int(settings.value("Settings/saveSettings"))
        else:
            self.saveSettings = 1
                      
        if self.saveSettings:
            QTimer.singleShot(0, self.load_initial_data)
            #QTimer.singleShot(0, self.load_initial_model)
        
        self.header = self.tableView.horizontalHeader()
        self.header.sectionDoubleClicked.connect(self.sort_table)
        
        self.search.textEdited.connect(self.update_ui)
        self.search.setFocus()
        self.searchNextButton.clicked.connect(self.update_ui)
        self.searchPrevButton.clicked.connect(self.update_ui)
        
        self.tableView.pressed.connect(self.update_ui)
        
        self.tableView.doubleClicked.connect(
                    lambda: self.handle_observation(ObservationDialog.SHOW))
        self.addButton.clicked.connect(
                    lambda: self.handle_observation(ObservationDialog.ADD))
        self.deleteButton.clicked.connect(
                    lambda: self.handle_observation(ObservationDialog.DELETE))
        
    def closeEvent(self, event):
        settings = QSettings()
        if self.saveSettings:
            db = self.dbfile if self.db is not None else ''
            settings.setValue("Database/LastDb", db)
            
            if self.tableView.model() is not None:
                settings.setValue("Database/DefaultModel", self.tableView.model().name)
            
                visible_fields = [not bool(self.tableView.isColumnHidden(i)) for i in range(0, self.tableView.model().columnCount())]
                settings.setValue("Database/visibleFields", visible_fields)
            settings.setValue("Settings/debugging", int(self.logger.debugging))
        
        settings.setValue("Settings/saveSettings", int(self.saveSettings))
    
    def load_initial_data(self):
        settings = QSettings()
        dbfile = unicode(settings.value("Database/LastDb"))
        modelname = unicode(settings.value("Database/DefaultModel"))
        if dbfile and QFile.exists(dbfile):
            self.load_db(dbfile, modelname=modelname)
            self.logger.debug("Loaded database %s with model %s" % (dbfile,
                                                                     modelname))
        
        if settings.value("Database/visibleFields"):
            visible_fields = [item for item in settings.value("Database/visibleFields")]
        
            # FIXME: in absence of QVariant, deal with values
            visible_fields = [False if item == 'false' else True for item in visible_fields]
            if not all(visible_fields):
                self.logger.debug("Hiding fields %s" % visible_fields)
            self.show_fields(visible_fields)

    def load_db(self, dbname, modelname=None):
        self.db = QSqlDatabase.addDatabase(self.dbtype)
        self.db.setDatabaseName(dbname)
        if not self.db.open():
            QMessageBox.warning(self, "Batabase connection",
                "Database Error: %s" % (self.db.lastError().text()))
            return
        self.dbfile = dbname
        
        if modelname not in self.models.model_names:
            modeldlg = ModelDialog(self.models.model_names)
            if modeldlg.exec_():
                modelname = modeldlg.selected_model()
        
        if modelname:
            self.load_model(modelname)
    
    def load_model(self, modelname):
        ''' Loads a specific database model and sets it to view.  
        '''
        try:
            model = self.models.get_model(modelname)
        except NotImplementedError, e:
            QMessageBox.warning(self, "Database model",
                "Database Model Error: %s" % str(e))
            return
        self.tableView.setModel(model(self))
        self.tableView.setItemDelegate(QSqlRelationalDelegate(self))
        self.tableView.setSelectionMode(QTableView.SingleSelection)
        self.tableView.setSelectionBehavior(QTableView.SelectRows)
        self.tableView.setColumnHidden(0, True)
        self.tableView.resizeColumnsToContents()
        self.update_ui()