Exemplo n.º 1
0
def descadastrar_linhas(app, dados):
    actions = 0
    reservas_changed = False

    for dados_linha, reservas in dados:
        linha = gerar_id_linha(*dados_linha[:2])
        for reserva in reservas:
            estado.reservas.discard(reserva)
            app.reservas.delete(reserva)
            reservas_changed = True

        app.contador_reservas['text'] = fm.form_cont_reservas(
            len(estado.reservas))

        t = minutos_dia(dados_linha.horario)

        del estado.linhas_entradas[linha]
        estado.linhas_possiveis.add((dados_linha.destino.title(), t))
        estado.horarios_linhas[t].remove(linha)
        estado.linhas_visiveis.remove(linha)
        app.contador_linhas['text'] = fm.form_cont_linhas(
            len(estado.linhas_visiveis))
        onibus_filhos = dados_linha.onibus.keys()
        monitoradas.onibus_visiveis -= onibus_filhos
        estado.onibus_invisiveis -= onibus_filhos
        app.contador_onibus['text'] = fm.form_cont_onibus(
            len(monitoradas.onibus_visiveis))
        app.linhas.delete(linha)

        actions += 1

    if not reservas_changed:
        app.abas.select(app.aba_linhas)

    return actions
Exemplo n.º 2
0
def csv_to_linha(app, linha, data_atual=monitoradas.data_atual):
    '''
        Cria e retorna um wrapper sobre a linha com base na string linha.
        Aqui está o formato do wrapper:

        atributos = {
            'validez': valor_booleano,
            'texto': 'Ok',
            'id': id_da_linha,
            'campus': campus,
            'horario': horario,
            'fileiras': fileiras,
            'inteira': inteira
        }

        Mas as propriedades são acessíveis pela sintaxe de objeto (wrapper.validez) em vez
        da sintaxe de dict (wrapper['validez'])

        Caso a reserva não seja válida, essa função verifica o erro e coloca uma mensagem de erro na propriedade
        "texto" do wrapper, além de atribuir False para a propriedade "validez".
    '''
    # note que type('', (), DICIONARIO) é utilizado para que possamos nos referir às propriedades com a sintaxe de
    # objeto, em vez da sintaxe de dicionário.
    # Ou seja, podemos usar OBJETO.PROPRIEDADE em vez de DICIONARIO['PROPRIEDADE'], o que ajuda no desenvolvimento,
    # já que a IDE é capaz de detectar propriedades inexistentes antes mesmo de o código rodar.
    try:
        campus, horario, assentos, inteira = map(
            str.strip, linha.split(',', 4)[:4])
    except ValueError:
        return type('', (), {'validez': False, 'texto': 'quantidade insuficiente de campos, esperava-se 4'})
    campus = campus.replace('-', ' ').strip()
    if campus == '':
        return type('', (), {'validez': False, 'texto': 'destino vazio'})
    try:
        horario = dt.datetime.strptime(horario, '%H:%M')
    except ValueError:
        return type('', (), {'validez': False, 'texto': f'horário não segue formato previsto: {data_atual.strftime("%H:%M")}'})
    try:
        fileiras = int(assentos)//2
        if fileiras not in range(1, cte.MAXIMO_NUMERO_DE_FILEIRAS + 1):
            return type('', (), {'validez': False, 'texto': f'número máximo de assentos livres fora do intervalo previsto: [1, {cte.MAXIMO_NUMERO_DE_FILEIRAS*4}]'})
    except ValueError:
        return type('', (), {'validez': False, 'texto': f'número máximo de assentos livres não é inteiro em [1, {4*cte.MAXIMO_NUMERO_DE_FILEIRAS}]'})
    try:
        inteira = round(float(inteira)*100 - 300)
        if inteira not in range(301):
            return type('', (), {'validez': False, 'texto': f'valor inteira fora do intervalo previsto: [3.0, 6.0]'})
    except ValueError:
        return type('', (), {'validez': False, 'texto': f'valor inteira não é float em [3.0, 6.0]'})

    linha = gerar_id_linha(campus, horario)
    if linha in estado.linhas_visiveis:
        return type('', (), {'validez': False, 'texto': 'linha existente'})
    elif linha in estado.linhas_entradas:
        return type('', (), {'validez': False, 'texto': 'linha desabilitada'})

    atributos = {'validez': True, 'texto': 'Ok', 'id': linha, 'campus': campus,
                 'horario': horario, 'fileiras': fileiras, 'inteira': inteira}
    return type('linha', (), atributos)
Exemplo n.º 3
0
def adicionar_linha(app):
    '''
        Adiciona uma linha com base nos campos de texto.
    '''
    # lemos todos os campos de texto
    campos = [
        dest.atualizar_destino(),
        date.update(app),
        vg.atualizar_vagas(),
        it.atualizar_inteira()
    ]

    for campo in campos:
        if popup.campos_invalidos[campo]():
            return
    # aqui, todos os campos de texto possuem valores válidos, então vamos criar a linha

    linhas = app.linhas
    destino = monitoradas.destino.get()
    tempo_exibido = monitoradas.tempo_exibido
    vagas = monitoradas.vagas.get()
    inteira = monitoradas.inteira.get()
    linha = gerar_id_linha(destino, tempo_exibido)
    # antes de inseri-la graficamente, temos que verificar se ela já existe
    if linha in estado.linhas_entradas:
        # Linha desabilitada. Deseja reabilitá-la?
        if linha not in estado.linhas_visiveis:
            texto = 'Linha desabilitada, deseja reabilitá-la?.'
            resposta = messagebox.askyesno(title='Linha existe',
                                           message=texto,
                                           default='yes')
            if resposta:
                app.linhas.reattach(linha, '', 0)
                estado.linhas_visiveis.add(linha)
                onibus_filhos_visiveis = set(app.linhas.get_children(linha))
                estado.onibus_invisiveis -= onibus_filhos_visiveis
                monitoradas.onibus_visiveis.update(onibus_filhos_visiveis)
                ctrl.update_action(app, 'Restaurar')

                monitoradas.historico_redo.clear()
                monitoradas.historico_undo.append(['show', [0], [linha]])
                app.linhas.selection_set(linha)
                app.contador_linhas['text'] = fm.form_cont_linhas(
                    len(estado.linhas_visiveis))
                app.contador_onibus['text'] = fm.form_cont_onibus(
                    len(monitoradas.onibus_visiveis))
                # nova ação: reabilitar
        else:
            app.linhas.see(linha)
            app.linhas.selection_set(linha)
        return
    h = minutos_dia(tempo_exibido)
    estado.linhas_possiveis.discard((destino, h))
    estado.horarios_linhas[h] = estado.horarios_linhas.get(h, set()).union(
        {linha})

    dest.add_destino(app)
    ctrl.update_action(app, 'add')
    linhas.insert(parent='',
                  index=0,
                  values=(destino, fm.form_tempo(tempo_exibido), vagas,
                          inteira),
                  iid=linha)
    estado.linhas_visiveis.add(linha)
    app.contador_linhas['text'] = fm.form_cont_linhas(
        len(estado.linhas_visiveis))

    estado.linhas_entradas[linha] = cte.ESTRUTURA_LINHA(
        destino, tempo_exibido,
        int(vagas) // 2, round(float(inteira) * 100 - 300), dict())

    data_atual = monitoradas.data_atual.replace(second=0, microsecond=0)
    for d in range(cte.MAXIMO_NUMERO_DE_DIAS_ATE_RESERVA + 1):
        partida = (data_atual + dt.timedelta(d)).replace(
            hour=tempo_exibido.hour, minute=tempo_exibido.minute)
        if data_atual <= partida <= data_atual + dt.timedelta(
                cte.MAXIMO_NUMERO_DE_DIAS_ATE_RESERVA):
            onibus = gerar_id_onibus(linha, partida)
            linhas.insert(parent=linha,
                          index='end',
                          values=('-', fm.form_data(partida), vagas, '-'),
                          iid=onibus)
            monitoradas.onibus_visiveis.add(onibus)
            estado.linhas_entradas[linha].onibus[onibus] = dict()
            app.contador_onibus['text'] = fm.form_cont_onibus(
                len(monitoradas.onibus_visiveis))

    app.contador_linhas['text'] = fm.form_cont_linhas(
        len(estado.linhas_visiveis))
    app.contador_onibus['text'] = fm.form_cont_onibus(
        len(monitoradas.onibus_visiveis))

    historico_undo = monitoradas.historico_undo
    historico_redo = monitoradas.historico_redo
    historico_redo.clear()
    historico_undo.append(['add', [[estado.linhas_entradas[linha], list()]]])
    linhas.selection_set(linha)
Exemplo n.º 4
0
def editar_linha(app):
    '''
        Edita informações sobre uma linha.
    '''
    selecao = app.linhas.selection()
    if len(selecao) != 1 or app.linhas.parent(selecao[0]) != '':
        texto = 'Selecione uma única linha.'
        messagebox.showwarning(title='Impossível Editar', message=texto)
        return
    [linha] = selecao
    dados_linha = estado.linhas_entradas[linha]
    # a condição a seguir é True sse existe algum ônibus com reservas na linha selecionada.
    if any(len(x) != 0 for x in dados_linha.onibus.values()):
        texto = 'Linha possui reservas.'
        messagebox.showwarning(title='Impossível Editar', message=texto)
        return

    campos = [
        dest.atualizar_destino(),
        date.update(app),
        vg.atualizar_vagas(),
        it.atualizar_inteira()
    ]

    for campo in campos:
        if popup.campos_invalidos[campo]():
            return

    destino_alterada = monitoradas.destino.get()
    tempo_exibido = monitoradas.tempo_exibido
    vagas_alterada = monitoradas.vagas.get()
    inteira_alterada = monitoradas.inteira.get()
    linha_alterada = gerar_id_linha(destino_alterada, tempo_exibido)

    h = minutos_dia(estado.linhas_entradas[linha].horario)

    if linha_alterada in estado.linhas_entradas:
        if linha_alterada in estado.linhas_visiveis:
            if linha != linha_alterada:
                texto = 'Linha já existe.'
                messagebox.showwarning(title='Impossível Editar',
                                       message=texto)
            elif dados_linha[2:4] != [
                    int(vagas_alterada) // 2,
                    round(float(inteira_alterada) * 100 - 300)
            ]:
                dados_linha_alterada = estado.linhas_entradas[
                    linha] = cte.ESTRUTURA_LINHA(
                        *dados_linha[:2],
                        int(vagas_alterada) // 2,
                        round(float(inteira_alterada) * 100 - 300),
                        dados_linha[-1])
                app.linhas.item(
                    linha,
                    values=campos_linha_formatados(dados_linha_alterada))

                app.linhas.selection_set(linha_alterada)
                monitoradas.historico_redo.clear()
                monitoradas.historico_undo.append(
                    ['change', dados_linha, dados_linha_alterada, False])
                app.contador_linhas['text'] = fm.form_cont_linhas(
                    len(estado.linhas_visiveis))
                app.contador_onibus['text'] = fm.form_cont_onibus(
                    len(monitoradas.onibus_visiveis))

        else:
            texto = 'Linha desabilitada, deseja reabilitá-la?'
            resposta = messagebox.askyesno(title='Impossível Editar',
                                           message=texto,
                                           default='no')
            if resposta:
                app.linhas.reattach(linha_alterada, '',
                                    app.linhas.index(linha))
                app.linhas.item(linha_alterada,
                                open=app.linhas.item(linha, 'open'))
                estado.linhas_visiveis.add(linha_alterada)
                onibus_filhos_visiveis = set(
                    app.linhas.get_children(linha_alterada))
                estado.onibus_invisiveis -= onibus_filhos_visiveis
                monitoradas.onibus_visiveis.update(onibus_filhos_visiveis)
                ctrl.update_action(app, 'Restaurar')
                estado.horarios_linhas[h].remove(linha)
                app.linhas.delete(linha)
                estado.linhas_visiveis.remove(linha)
                for onibus in estado.linhas_entradas[linha].onibus:
                    monitoradas.onibus_visiveis.discard(onibus)
                    estado.onibus_invisiveis.discard(onibus)

                monitoradas.historico_redo.clear()
                monitoradas.historico_undo.append([
                    'change', estado.linhas_entradas[linha],
                    estado.linhas_entradas[linha_alterada], True
                ])
                estado.linhas_possiveis.add((dados_linha.destino.title(), h))
                del estado.linhas_entradas[linha]
                app.linhas.selection_set(linha_alterada)
                app.contador_linhas['text'] = fm.form_cont_linhas(
                    len(estado.linhas_visiveis))
                app.contador_onibus['text'] = fm.form_cont_onibus(
                    len(monitoradas.onibus_visiveis))
        return
    h_alt = tempo_exibido.hour * 60 + tempo_exibido.minute
    estado.linhas_possiveis.remove((destino_alterada, h_alt))
    estado.linhas_possiveis.add((dados_linha.destino.title(), h))
    estado.horarios_linhas[h].remove(linha)
    estado.horarios_linhas[h_alt] = estado.horarios_linhas.get(
        h_alt, set()).union({linha_alterada})
    dest.add_destino(app)
    ctrl.update_action(app, 'change')
    indice = app.linhas.index(linha)
    app.linhas.insert(parent='',
                      index=indice,
                      values=(destino_alterada, fm.form_tempo(tempo_exibido),
                              vagas_alterada, inteira_alterada),
                      iid=linha_alterada,
                      open=app.linhas.item(linha, 'open'))
    app.linhas.delete(linha)
    estado.linhas_visiveis.remove(linha)
    estado.linhas_visiveis.add(linha_alterada)

    onibus_filhos = dict()

    data_atual = monitoradas.data_atual.replace(second=0, microsecond=0)
    for d in range(cte.MAXIMO_NUMERO_DE_DIAS_ATE_RESERVA + 1):
        partida = (data_atual + dt.timedelta(d)).replace(
            hour=tempo_exibido.hour, minute=tempo_exibido.minute)
        if data_atual <= partida <= data_atual + dt.timedelta(
                cte.MAXIMO_NUMERO_DE_DIAS_ATE_RESERVA):
            onibus = gerar_id_onibus(linha_alterada, partida)
            app.linhas.insert(parent=linha_alterada,
                              index='end',
                              values=('-', fm.form_data(partida),
                                      vagas_alterada, '-'),
                              iid=onibus)
            monitoradas.onibus_visiveis.add(onibus)
            onibus_filhos[onibus] = dict()

    estado.linhas_entradas[linha_alterada] = cte.ESTRUTURA_LINHA(
        destino_alterada, tempo_exibido,
        int(vagas_alterada) // 2, round(float(inteira_alterada) * 100 - 300),
        onibus_filhos)

    for onibus in estado.linhas_entradas[linha].onibus:
        monitoradas.onibus_visiveis.discard(onibus)
        estado.onibus_invisiveis.discard(onibus)

    monitoradas.historico_redo.clear()
    monitoradas.historico_undo.append([
        'change', estado.linhas_entradas[linha],
        estado.linhas_entradas[linha_alterada], False
    ])

    del estado.linhas_entradas[linha]
    app.contador_linhas['text'] = fm.form_cont_linhas(
        len(estado.linhas_visiveis))
    app.contador_onibus['text'] = fm.form_cont_onibus(
        len(monitoradas.onibus_visiveis))

    ctrl.update_action(app, 'change')
    app.linhas.selection_set(linha_alterada)
Exemplo n.º 5
0
def csv_to_reserva(app, linha, data_presente=monitoradas.data_atual, data_maxima=monitoradas.data_atual + dt.timedelta(cte.MAXIMO_NUMERO_DE_DIAS_ATE_RESERVA)):
    '''
        Cria e retorna um wrapper sobre a reserva com base na string linha.
        Aqui está o formato do wrapper:

        wrapper = {
            'validez': valor_booleano,
            'texto': 'Ok',
            'reserva': id_da_reserva,
            'campus': id_do_campus,
            'partida': partida,
            'assento': assento,
            'passagem': passagem,
            'inteira': inteira,
            'linha': id_da_linha,
            'onibus': id_do_onibus
        }

        Mas as propriedades são acessíveis pela sintaxe de objeto (wrapper.validez) em vez
        da sintaxe de dict (wrapper['validez'])

        Caso a reserva não seja válida, essa função verifica o erro e coloca uma mensagem de erro na propriedade
        "texto" do wrapper, além de atribuir False para a propriedade "validez".
    '''
    # note que type('', (), DICIONARIO) é utilizado para que possamos nos referir às propriedades com a sintaxe de
    # objeto, em vez da sintaxe de dicionário.
    # Ou seja, podemos usar OBJETO.PROPRIEDADE em vez de DICIONARIO['PROPRIEDADE'], o que ajuda no desenvolvimento,
    # já que a IDE é capaz de detectar propriedades inexistentes antes mesmo de o código rodar.
    try:
        campus, partida, assento, * \
            passagem = map(str.strip, linha.split(',', 4)[:4])
    except ValueError:
        return type('', (), {'validez': False, 'texto': 'quantidade insuficiente de campos, esperava-se ao menos 3'})
    campus = campus.replace('-', ' ').strip()
    if campus == '':
        return type('', (), {'validez': False, 'texto': 'destino vazio'})
    try:
        partida = dt.datetime.strptime(partida, '%d/%m/%y %H:%M')
        if not data_presente <= partida <= data_maxima:
            return type('', (), {'validez': False, 'texto': 'data fora do intervalo previsto'})
    except ValueError:
        return type('', (), {'validez': False, 'texto': f'data não segue formato previsto: {data_maxima.strftime("%d/%m/%y %H:%M")}'})
    try:
        assento = int(assento)
        if assento not in range(1, 4*cte.MAXIMO_NUMERO_DE_FILEIRAS + 1):
            return type('', (), {'validez': False, 'texto': 'assento fora do intervalo previsto'})
    except ValueError:
        return type('', (), {'validez': False, 'texto': f'assento não é inteiro em [1, {4*cte.MAXIMO_NUMERO_DE_FILEIRAS}]'})
    if passagem == []:
        passagem = cte.PASSAGEM_INDICE['inteira']
    else:
        passagem = cte.PASSAGEM_INDICE.get(passagem[0].lower(), None)
        if passagem is None:
            return type('', (), {'validez': False, 'texto': 'tipo de passagem inválida'})

    linha = gerar_id_linha(campus, partida)
    if linha not in estado.linhas_entradas:
        return type('', (), {'validez': False, 'texto': 'linha inexistente'})
    elif linha not in estado.linhas_visiveis:
        return type('', (), {'validez': False, 'texto': 'linha desabilitada'})

    onibus = gerar_id_onibus(linha, partida)
    if onibus in estado.onibus_invisiveis:
        return type('', (), {'validez': False, 'texto': 'ônibus desabilitado'})
    if assento in estado.linhas_entradas[linha].onibus[onibus]:
        return type('', (), {'validez': False, 'texto': 'assento reservado'})
    num_fileiras = estado.linhas_entradas[linha].fileiras
    shift = (sum(coordenadas_assento(assento, num_fileiras)) + 1) % 2
    assentos_indisponiveis = {assento_coordenadas(
        i, 2 * j + (i + shift) % 2, num_fileiras) for j in range(2) for i in range(num_fileiras)}
    if assento in assentos_indisponiveis:
        return type('', (), {'validez': False, 'texto': 'assento indisponível'})
    reserva = gerar_id_reserva(onibus, assento, passagem)
    inteira = estado.linhas_entradas[linha].inteira
    atributos = {'validez': True, 'texto': 'Ok', 'reserva': reserva, 'campus': campus, 'partida': partida,
                 'assento': assento, 'passagem': passagem, 'inteira': inteira, 'linha': linha, 'onibus': onibus}
    return type('reserva', (), atributos)
Exemplo n.º 6
0
def mudar(app, dados_anterior, dados_alterada, existia):
    app.abas.select(app.aba_linhas)
    linha_anterior = gerar_id_linha(*dados_anterior[:2])
    linha_alterada = gerar_id_linha(*dados_alterada[:2])
    if linha_anterior == linha_alterada:
        app.linhas.item(linha_anterior,
                        values=campos_linha_formatados(dados_alterada))
        app.linhas.selection_set(linha_alterada)
        app.contador_linhas['text'] = fm.form_cont_linhas(
            len(estado.linhas_visiveis))
        app.contador_onibus['text'] = fm.form_cont_onibus(
            len(monitoradas.onibus_visiveis))
        return 1
    indice = app.linhas.index(linha_anterior)
    expanded = app.linhas.item(linha_anterior, 'open')
    t = minutos_dia(dados_anterior.horario)
    estado.horarios_linhas[t].remove(linha_anterior)
    estado.linhas_visiveis.remove(linha_anterior)
    onibus_filhos = dados_anterior.onibus.keys()
    monitoradas.onibus_visiveis -= onibus_filhos
    estado.onibus_invisiveis -= onibus_filhos
    del estado.linhas_entradas[linha_anterior]
    app.linhas.delete(linha_anterior)
    estado.linhas_possiveis.add((dados_anterior.destino.title(), t))

    if existia:
        app.linhas.reattach(linha_alterada, '', indice)
        app.linhas.item(linha_alterada, open=expanded)
        estado.linhas_visiveis.add(linha_alterada)
        onibus_filhos_visiveis = set(app.linhas.get_children(linha_alterada))
        estado.onibus_invisiveis -= onibus_filhos_visiveis
        monitoradas.onibus_visiveis.update(onibus_filhos_visiveis)
    else:
        t = minutos_dia(dados_alterada.horario)
        assentos = dados_alterada.fileiras * 2
        estado.horarios_linhas[t] = estado.horarios_linhas.get(t, set()).union(
            {linha_alterada})
        app.linhas.insert(parent='',
                          index=indice,
                          values=campos_linha_formatados(dados_alterada),
                          iid=linha_alterada,
                          open=expanded)
        estado.linhas_visiveis.add(linha_alterada)
        estado.linhas_possiveis.remove((dados_alterada.destino.title(), t))

        estado.linhas_entradas[linha_alterada] = cte.ESTRUTURA_LINHA(
            *dados_alterada[:-1], dict())

        data_atual = monitoradas.data_atual.replace(second=0, microsecond=0)
        for d in range(cte.MAXIMO_NUMERO_DE_DIAS_ATE_RESERVA + 1):
            partida = (data_atual + dt.timedelta(d)).replace(
                hour=dados_alterada.horario.hour,
                minute=dados_alterada.horario.minute)
            if data_atual <= partida <= data_atual + dt.timedelta(
                    cte.MAXIMO_NUMERO_DE_DIAS_ATE_RESERVA):
                onibus = gerar_id_onibus(linha_alterada, partida)
                app.linhas.insert(parent=linha_alterada,
                                  index='end',
                                  values=('-', fm.form_data(partida), assentos,
                                          '-'),
                                  iid=onibus)
                monitoradas.onibus_visiveis.add(onibus)
                estado.linhas_entradas[linha_alterada].onibus[onibus] = dict()

    app.contador_onibus['text'] = fm.form_cont_onibus(
        len(monitoradas.onibus_visiveis))
    app.contador_linhas['text'] = fm.form_cont_linhas(
        len(estado.linhas_visiveis))
    app.linhas.selection_set(linha_alterada)

    return 1
Exemplo n.º 7
0
def recadastrar_linhas(app, dados):
    actions = 0
    reservas_changed = False

    app.linhas.selection_set(*[])
    app.reservas.selection_set(*[])

    for dados_linha, reservas in dados:
        linha = gerar_id_linha(*dados_linha[:2])

        estado.linhas_entradas[linha] = cte.ESTRUTURA_LINHA(
            *dados_linha[:-1], dict())

        for reserva in reservas:
            estado.reservas.add(reserva)
            app.reservas.insert(parent='',
                                index=0,
                                values=campos_reserva_formatados(reserva),
                                iid=reserva)
            reservas_changed = True

        app.contador_reservas['text'] = fm.form_cont_reservas(
            len(estado.reservas))

        t = minutos_dia(dados_linha.horario)
        estado.linhas_possiveis.remove((dados_linha.destino.title(), t))

        estado.horarios_linhas[t] = estado.horarios_linhas.get(t, set()).union(
            {linha})
        estado.linhas_visiveis.add(linha)
        app.contador_linhas['text'] = fm.form_cont_linhas(
            len(estado.linhas_visiveis))

        app.linhas.insert(parent='',
                          index=0,
                          values=campos_linha_formatados(dados_linha),
                          iid=linha)

        data_atual = monitoradas.data_atual.replace(second=0, microsecond=0)
        minutos_atual = data_atual.hour * 60 + data_atual.minute

        if t == minutos_atual:
            periodo = range(cte.MAXIMO_NUMERO_DE_DIAS_ATE_RESERVA + 1)
        elif t < minutos_atual:
            periodo = range(1, cte.MAXIMO_NUMERO_DE_DIAS_ATE_RESERVA + 1)
        else:
            periodo = range(cte.MAXIMO_NUMERO_DE_DIAS_ATE_RESERVA)

        for d in periodo:
            partida = (data_atual + dt.timedelta(d)).replace(
                hour=dados_linha.horario.hour,
                minute=dados_linha.horario.minute)
            onibus = gerar_id_onibus(linha, partida)
            assentos = dados_linha.onibus.get(onibus, dict())
            app.linhas.insert(
                parent=linha,
                index='end',
                values=('-', fm.form_data(partida),
                        2 * int(dados_linha.fileiras) - len(assentos), '-'),
                iid=onibus)
            monitoradas.onibus_visiveis.add(onibus)
            app.contador_onibus['text'] = fm.form_cont_onibus(
                len(monitoradas.onibus_visiveis))
            estado.linhas_entradas[linha].onibus[onibus] = assentos

        app.linhas.selection_add(linha)
        app.reservas.selection_add(*reservas)

        actions += 1

    if not reservas_changed:
        app.abas.select(app.aba_linhas)

    return actions