0

I am trying to create a tool in Python that allows the user to select a date or a range of dates through a calendar within a form using npyscreen.

The calendar should allow the user to select the month and year within a range of dates from November 1, 2012 to December 31, 2022.

I have tried using the Grid widget of npyscreen to display the calendar, but I cannot get all the dates to display within the form. Specifically, the Grid widget seems to have limited dimensions, which do not allow me to display all the dates of the calendar.

Below is the code I am using to create the calendar. Can you please help me resolve the issue?

import curses
import npyscreen
from datetime import datetime, timedelta

npyscreen.disableColor()

def terminal_dimensions():
    return curses.initscr().getmaxyx()

class App(npyscreen.NPSApp):
    def main(self):
        form = npyscreen.FormBaseNew(name = "Tool to extract data")
        column_height = terminal_dimensions()[0] - 30
        widget_calendar = form.add(CalendarWidget, name = "CALENDAR", relx=2, rely=2, max_width=95, max_height=column_height)
        self.selected_dates_widget = form.add(SelectedDatesWidget, name = "SELECTED DATES", relx=100, rely=2, max_height=column_height)
        widget_fileman = form.add(npyscreen.BoxTitle, name = "FILE MANAGER", relx=2, rely=column_height + 2, max_height=column_height)
        widget_messages = form.add(npyscreen.BoxTitle, name = "MESSAGES", rely=column_height + 24, max_height=4)
        form.edit()

class CalendarWidget(npyscreen.GridColTitles):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.col_titles = ['Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su']
        self.col_width = 3
        self.row_height = 2
        self.start_date = datetime(2012, 11, 1)
        self.end_date = datetime(2022, 12, 31)
        self.current_date = datetime.now()
        self.display_month = self.current_date.month
        self.display_year = self.current_date.year
        self.selected_dates = []
        self.update_values()

    def update_values(self):
        days_in_month = (self.start_date.replace(year=self.display_year, month=self.display_month, day=1) - timedelta(days=1)).day
        first_day_of_month = datetime(self.display_year, self.display_month, 1).weekday()
        self.values = [[''] * 7 for _ in range(6)]
        current_day = 1
        for row in range(6):
            for col in range(7):
                if row == 0 and col < first_day_of_month:
                    continue
                if current_day > days_in_month:
                    break
                self.values[row][col] = current_day
                current_day += 1

    def when_cursor_moved(self):
        self.parent.selected_dates_widget.reset_selection()
        self.parent.display()

    def get_selected_objects(self):
        return self.selected_dates

    def when_value_edited(self):
        self._old_value = self.value
        super().when_value_edited()
        if not self.get_selected_objects():
            return
        selected_date = datetime(self.display_year, self.display_month, int(self.get_selected_objects()[0]))
        self.parent.selected_dates_widget.update_selection(selected_date)
        self.parent.display()

class SelectedDatesWidget(npyscreen.BoxTitle):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.values = []

    def reset_selection(self):
        self.values = []
        self.display()

    def update_selection(self, selected_date):
        self.values.append(selected_date.strftime('%Y-%m-%d'))
        self.display()

if __name__ == "__main__":
    app = App()
    try:
        app.run()
    except:
        curses.endwin()

Thank you in advance for your help.

his is an image of the program as it appears now. date picker

bonzix
  • 45
  • 5

0 Answers0