def __init__(self, **kwargs):
        """
            Installing all the required widgets for the layout of kivy app
        """
        super().__init__(**kwargs)
        self.song_list = SongList()

        #   Bottom status label and Top count label
        self.top_label = Label(text="", id="count_label")
        self.status_label = Label(text="")

        # layout widget left part
        self.sort_label = Label(text="Sort by:")
        # Putting default sort method as Artist
        self.spinner = Spinner(text='Artist',
                               values=('Artist', 'Title', 'Year', 'Required'))
        self.add_song_label = Label(text="Add New Song...")
        self.title_label = Label(text="Title:")
        self.title_text_input = TextInput(write_tab=False, multiline=False)
        self.artist_label = Label(text="Artist:")
        self.artist_text_input = TextInput(write_tab=False, multiline=False)
        self.year_label = Label(text="Year:")
        self.year_text_input = TextInput(write_tab=False, multiline=False)

        # To add and clear for the bottom widget
        self.add_song_button = Button(text='Add Song')
        self.clear_button = Button(text='Clear')
Beispiel #2
0
 def __init__(self, **kwargs):
     """Construct main app"""
     super(SongsToLearnApp, self).__init__(**kwargs)
     self.song_list = SongList()
     self.sort_choices = ["title", "artist", "year", "is_required"]
     self.current_sort = self.sort_choices[0]
     self.song_list.load_songs()
Beispiel #3
0
 def __init__(self, **kwargs):
     """
     :Parameter:**kwargs
     Initiate the self.song_list to SongList() class
     :return:None
     """
     super(SongsToLearnApp, self).__init__(**kwargs)
     self.song_list = SongList()
Beispiel #4
0
 def __init__(self, **kwargs):
     """
     construct the main app
     """
     super(SongsToLearnApp, self).__init__(**kwargs)
     self.sort_by = ["Title", "Artist", "Year", "Is_required"]# Create a list for "spinner"
     self.current_state = self.sort_by[0]# Set the "Title" as the default option
     self.song_list = SongList()
     self.song_list.load_songs()
Beispiel #5
0
 def __init__(self, **kwargs):
     """
     Constructs App, sets self.songs to SongList class, sets self.song to Song class and loads the specified song
     file with self.songs.load_songs
     """
     self.songs = SongList()
     self.song = Song()
     self.songs.load_songs(FILE_NAME)
     super(SongsToLearnApp, self).__init__(**kwargs)
Beispiel #6
0
 def __init__(self, **kwargs):
     """
     Construct main app
     """
     super(LearnSongsApp, self).__init__(**kwargs)
     self.song_list = SongList()
     self.sort_choices = ["year", "artist"]
     self.current_sort = self.sort_choices[0]
     self.song_list.load_songs()
Beispiel #7
0
    def __init__(self, parent=None):
        super(MusicMainWindow, self).__init__(parent)
        self._settings = QSettings("Raul Sangonzalo", "Musician Suite")
        self.setWindowTitle("Musician Suite")

        os.chdir(os.path.dirname(os.path.abspath(__file__)))
        resourcesPath = os.getcwd()
        print(resourcesPath)
        resourcesPath = os.path.join(resourcesPath, "resources")
        print(resourcesPath)

        self.MAIN_ICON = QIcon(os.path.join(resourcesPath, "test.ico"))
        self.ICON0 = QIcon(QPixmap(os.path.join(resourcesPath, "icon0.png")))
        self.ICON1 = QIcon(QPixmap(os.path.join(resourcesPath, "icon1.png")))
        self.setWindowIcon(self.MAIN_ICON)

        self.fileMenu = QMenu("File")

        self.databaseMenu = QMenu("Database")
        self.databaseMenu.addAction("Create new database")
        self.databaseMenu.addAction("Import database")
        # self.databaseMenu.triggered.connect(self.menuTriggered)

        self.fileMenu.addMenu(self.databaseMenu)
        self.fileMenu.addSeparator()
        self.fileMenu.addAction("Exit")

        self.aboutMenu = QMenu("Help")
        self.aboutMenu.addAction("About")

        self.menuBar().addMenu(self.fileMenu)
        self.menuBar().addMenu(self.aboutMenu)
        self.menuBar().triggered.connect(self.menuTriggered)

        self.songList = SongList()
        self.recordIdeas = RecordIdeas()

        toolBar = QToolBar("title")

        toolBar.addAction(self.ICON0, "Songs")
        toolBar.addAction(self.ICON1, "Record Ideas")

        # not sure if this is the best way forward
        self.stackedWidget = QStackedWidget()
        self.stackedWidget.addWidget(self.songList)
        self.stackedWidget.addWidget(self.recordIdeas)

        toolBar.actionTriggered.connect(self.toolBarActionTriggered)
        self.addToolBar(Qt.TopToolBarArea, toolBar)

        self.setCentralWidget(self.stackedWidget)
Beispiel #8
0
 def __init__(self, **kwargs):
     """
     Initiate song_list to SongList class
     Initiate sort_choices as an array
     Initiate the current sorting option as "title"
     Initiate the function load_songs to load csv file
     :param kwargs:
     returns None
     """
     super(SongsToLearnApp, self).__init__(**kwargs)
     self.song_list = SongList()
     self.sort_choices = ["title", "artist", "year", "is_required"]
     self.current_sort = self.sort_choices[0]
     self.song_list.load_songs()
Beispiel #9
0
 def build(self):
     self.title = "Song List"
     self.root = Builder.load_file('app.kv')
     # Used to identify which song button is pressed
     # self.song_button_id = []
     # using the SongList Class
     self.song_list = SongList()
     self.song_list.load_songs("songs.csv")
     self.create_song_list()
     # Used for sorting
     self.sort_codes = SORT_TYPE.keys()
     self.current_state = self.sort_codes[0]
     # Button variable for the learning of songs
     return self.root
Beispiel #10
0
    def build(self):
        SongList()  # initialise an empty list on program start
        Window.size = (900, 600)
        self.title = 'Songs to Learn 2.0'
        self.root = Builder.load_file('app.kv')
        songs_list = self.load_songs()
        self.create_entry_grids(songs_list)
        self.root.ids.message_box.text = '~~~Welcome to Songs to Learn 2.0~~~'

        return self.root
Beispiel #11
0
    def learned(self, test_arg):
        #marks songs as learnt
        test_arg.state = 'down'
        song_list = SongList().load_songs()
        index = 0
        loop_counter = 0
        if '(learned)' in test_arg.text:
            self.root.ids.bottom_text.text = 'song already learned'
        else:
            self.root.ids.bottom_text.text = 'song learned'
        #searches through list for songs
        for song in song_list:
            format_string = str('"' + song[0] + '" by ' + song[1] + ' (' +
                                song[2] + ')')
            print(test_arg.text)
            print(format_string)
            if test_arg.text in format_string:
                index = loop_counter
            loop_counter += 1
        SongList().song_marked_learned(index)

        print(str(index))
Beispiel #12
0
class SongsToLearnApp(App):
    song_list = SongList()

    def build(self):
        self.title = "Song Learn 3.0"
        self.root = Builder.load_file('app.kv')
        self.display_list()
        return self.root

    def display_list(self, sur_list=[]):
        self.root.ids.entries_box.clear_widgets()
        store_songs = self.song_list.get_songs('r')
        if sur_list != []:
            store_songs = []
            store_songs = sur_list
        for song in store_songs:

            temp_button = Button(text=Song().print_str(str(song)))
            temp_button.bind(on_release=self.press_entry)
            # add the button to the "entries_box" using add_widget()
            self.root.ids.entries_box.add_widget(temp_button)

    def press_entry(self, arg):
        # print(arg.text)
        if ('learned' in arg.text):
            self.root.ids.bottom_text.text = "Song is already learned, plz select another one"
        else:
            self.song_list.add_file(arg.text)
            self.display_list()

    def press_clear(self):
        self.root.ids.add_title.text = ''
        self.root.ids.add_artist.text = ''
        self.root.ids.add_year.text = ''

    def sort(self, text):
        key = 0
        if 'title' in text:
            key = 0
        elif 'artist' in text:
            key = 1
        else:
            key = 2
        new_list = self.song_list.sort(key)
        self.display_list(new_list)

    def add_song(self):
        form_song = self.root.ids.add_title.text + ',' + self.root.ids.add_artist.text + ',' + self.root.ids.add_year.text + ',n\n'
        self.song_list.get_songs('a', form_song)
        self.display_list()
Beispiel #13
0
 def __init__(self, **kwargs):
     super(Song_To_LearnApp, self).__init__(**kwargs)
     self.album = SongList()
     self.album.load_songs("songs.csv")
     self.album.kivy_load_songs()
Beispiel #14
0
class LearnSongsApp(App):
    """
        Main program: show the list of songs by GUI
        """
    status_text = StringProperty()  # the first status text
    status_text2 = StringProperty()  # the second status text
    current_sort = StringProperty()  # the current sorting of song list
    sort_choices = ListProperty()  # the sorting options of song list

    def __init__(self, **kwargs):
        """
        Construct main app
        """
        super(LearnSongsApp, self).__init__(**kwargs)
        self.song_list = SongList()
        self.sort_choices = ["year", "artist"]
        self.current_sort = self.sort_choices[0]
        self.song_list.load_songs()

    def build(self):
        """
        Build the Kivy GUI
        """
        self.title_ = "Songs to learn 2.0 by Chen Jianjian"  # Name the GUI's name
        self.root = Builder.load_file('app.kv')  # Connect to Kivy app
        self.create_buttons()  # Create the songs button
        return self.root

    def change_sort(self, sorting_choice):
        """
        change the sorting of the song list

        """
        self.song_list.sort(sorting_choice)
        self.root.ids.entriesBox.clear_widgets()
        self.create_buttons()
        sort_index = self.sort_choices.index(sorting_choice)
        self.current_sort = self.sort_choices[sort_index]

    def create_buttons(self):
        """
        Create Songs' buttons from the csv file

        """
        num_song = len(self.song_list.list_songs)  # Count the number of songs
        learned_song = 0
        for song in self.song_list.list_songs:  # find the songs
            name = self.button_Text(song.title, song.artist, song.year,song.is_required)  # showing the information in be the button)
            learned = song.is_required
            if learned == 'n':
                background_color = (1, 2, 1, 0.7)#if the song id learned show this color
                learned_song += 1
            else:
                # If the song is not learned show blue color
                background_color = (1, 3, 4, 0.6)
            # clicking a song to learn
            temp_button = Button(text=name,background_color=background_color)  # Add the song learned
            temp_button.bind(on_release=self.press_song)  # show the message of the status
            self.root.ids.entriesBox.add_widget(temp_button)  # add the song to the Kivy app
        self.status_text = 'To Learned: {}  Learned: {}'.format(num_song-learned_song,learned_song)

    def button_Text(self, title, artist, year, learned):  # show  messages
        if learned == "n":
            display_text = "{} by {} {} (Learned)".format(title,artist,year)
        else:
            display_text = "{} by {} {}".format(title,artist,year)

        return display_text

    def press_song(self, button):  # when you press the song button
        buttonText = button.text  # Determine the text on the buttons
        selectedSong = Song()
        for song in self.song_list.list_songs:
            songDisplayText = self.button_Text(song.title, song.artist, song.year, song.is_required)
            # show text in Button
            if buttonText == songDisplayText:
                selectedSong = song
                break

        selectedSong.add_learned()
        self.root.ids.entriesBox.clear_widgets()  # Apply to Kivy
        self.create_buttons()

        self.status_text2 = "You have learned {}".format(selectedSong.title)  # Display the status text 2

    def add_songs(self):
        """
        add a song to learn
        """

        # Check if have empty inputs
        if self.root.ids.song_title.text == "" or self.root.ids.song_artist.text == "" or self.root.ids.song_year.text == "":
            self.root.ids.status2.text = "All fields must be completed"
            return
        try:
            # Define song items inputted
            song_title = str(self.root.ids.song_title.text)
            song_artist = str(self.root.ids.song_artist.text)
            song_year = int(self.root.ids.song_year.text)
            is_required = "y"

            # Add the song to the song list
            self.song_list.add_to_list(song_title, song_artist, song_year, is_required)
            temp_button = Button(text=self.button_Text(song_title, song_artist, song_year, is_required))
            temp_button.bind(on_release=self.press_song)

            # the new song button color
            temp_button.background_color = (1, 3, 4, 0.6)
            self.root.ids.entriesBox.add_widget(temp_button)

            # empty inputs
            self.root.ids.song_title.text = ""
            self.root.ids.song_artist.text = ""
            self.root.ids.song_year.text = ""

        except ValueError:  # Display error when year input is not a number
            self.status_text2 = "Please enter a valid year"
        self.song_list.save_songs()

    def press_clear(self):
        """
        Clear status text and inputs

        """
        self.status_text = ""  # Clear status_text
        self.status_text2 = ""  # Clear status_text2
        self.root.ids.song_title.text = ''  # Clear title input
        self.root.ids.song_artist.text = ''  # Clear artist input
        self.root.ids.song_year.text = ''  # Clear year input
Beispiel #15
0
class MusicMainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MusicMainWindow, self).__init__(parent)
        self._settings = QSettings("Raul Sangonzalo", "Musician Suite")
        self.setWindowTitle("Musician Suite")

        os.chdir(os.path.dirname(os.path.abspath(__file__)))
        resourcesPath = os.getcwd()
        print(resourcesPath)
        resourcesPath = os.path.join(resourcesPath, "resources")
        print(resourcesPath)

        self.MAIN_ICON = QIcon(os.path.join(resourcesPath, "test.ico"))
        self.ICON0 = QIcon(QPixmap(os.path.join(resourcesPath, "icon0.png")))
        self.ICON1 = QIcon(QPixmap(os.path.join(resourcesPath, "icon1.png")))
        self.setWindowIcon(self.MAIN_ICON)

        self.fileMenu = QMenu("File")

        self.databaseMenu = QMenu("Database")
        self.databaseMenu.addAction("Create new database")
        self.databaseMenu.addAction("Import database")
        # self.databaseMenu.triggered.connect(self.menuTriggered)

        self.fileMenu.addMenu(self.databaseMenu)
        self.fileMenu.addSeparator()
        self.fileMenu.addAction("Exit")

        self.aboutMenu = QMenu("Help")
        self.aboutMenu.addAction("About")

        self.menuBar().addMenu(self.fileMenu)
        self.menuBar().addMenu(self.aboutMenu)
        self.menuBar().triggered.connect(self.menuTriggered)

        self.songList = SongList()
        self.recordIdeas = RecordIdeas()

        toolBar = QToolBar("title")

        toolBar.addAction(self.ICON0, "Songs")
        toolBar.addAction(self.ICON1, "Record Ideas")

        # not sure if this is the best way forward
        self.stackedWidget = QStackedWidget()
        self.stackedWidget.addWidget(self.songList)
        self.stackedWidget.addWidget(self.recordIdeas)

        toolBar.actionTriggered.connect(self.toolBarActionTriggered)
        self.addToolBar(Qt.TopToolBarArea, toolBar)

        self.setCentralWidget(self.stackedWidget)

    # quick fix, need better handling of what action is, not text
    def menuTriggered(self, action):
        if action.text() == 'Exit':
            msg = QMessageBox.question(
                None, "Close Application", "Do you want to close the application completely?")
            if msg == QMessageBox.Yes:
                sys.exit(1)
        # same as initial prompt
        elif action.text() == "Create new database":
            fileDialog = QFileDialog(filter="SQLite music database (*.db)")
            fileDialog.setAcceptMode(QFileDialog.AcceptSave)
            fileDialog.setDefaultSuffix("db")
            fileDialog.exec()
            dbName = fileDialog.selectedFiles()
            if dbName[0] != '':
                print(dbName[0])
                self._settings.setValue("currentDatabase", dbName)
                createTables()
                self.songList.populateList()
                self.recordIdeas.populateList()
        # same as initial prompt
        elif action.text() == "Import database":
            dbName = QFileDialog().getOpenFileName(
                self, filter="SQLite music database (*.db)", options=QFileDialog.DontUseNativeDialog)
            if dbName[0] != '':
                print(dbName[0])
                self._settings.setValue("currentDatabase", dbName[0])
                self.songList.populateList()
                self.recordIdeas.populateList()

        elif action.text() == "About":
            self.aboutDialog = QDialog()
            self.aboutDialog.setModal(True)
            self.aboutDialog.setWindowTitle("About")
            self.aboutDialog.setWindowIcon(self.MAIN_ICON)

            text = """<p style="text-align:center;"><b>Musician Suite 0.1 beta</b><br/><br/><br/>Created by Raúl Sangonzalo</p>
                Any bugs of suggestions, you can contact me at<p style="text-ali
                gn:center;"><i>- [email protected]<br/>- github.com/raulsangonzalo/musiciansuite</i></p>
                UI support built with PyQt5<br/>

                Music Player icons made by xnimrodx from www.flaticon.com<br/>
                Other music icons downloaded from https://icons8.com"""
            layout = QHBoxLayout(self.aboutDialog)
            label = QLabel(text)
            label.setTextInteractionFlags(Qt.TextSelectableByMouse)
            layout.addWidget(label)
            self.aboutDialog.show()

    def toolBarActionTriggered(self, action):  # quick fix
        if action.text() == "Songs":
            self.stackedWidget.setCurrentWidget(self.songList)
        elif action.text() == "Record Ideas":
            self.stackedWidget.setCurrentWidget(self.recordIdeas)
        elif action.text() == "Composition Analysis":
            pass

    def closeEvent(self, event):
        event.ignore()  # so app never closes
        self.hide()
class SongsList(App):
    def __init__(self, **kwargs):
        """
            Installing all the required widgets for the layout of kivy app
        """
        super().__init__(**kwargs)
        self.song_list = SongList()

        #   Bottom status label and Top count label
        self.top_label = Label(text="", id="count_label")
        self.status_label = Label(text="")

        # layout widget left part
        self.sort_label = Label(text="Sort by:")
        # Putting default sort method as Artist
        self.spinner = Spinner(text='Artist',
                               values=('Artist', 'Title', 'Year', 'Required'))
        self.add_song_label = Label(text="Add New Song...")
        self.title_label = Label(text="Title:")
        self.title_text_input = TextInput(write_tab=False, multiline=False)
        self.artist_label = Label(text="Artist:")
        self.artist_text_input = TextInput(write_tab=False, multiline=False)
        self.year_label = Label(text="Year:")
        self.year_text_input = TextInput(write_tab=False, multiline=False)

        # To add and clear for the bottom widget
        self.add_song_button = Button(text='Add Song')
        self.clear_button = Button(text='Clear')

    def songs_sort(self, *args):
        """
        The code that handle the sorts base on the click of the spinner
        """
        self.song_list.sort(self.spinner.text)
        self.root.ids.rightLayout.clear_widgets()
        self.right_widgets()

    def build(self):
        """
            opening the kivy app and putting a little object
        """
        self.title = "Songs List 2.0"
        self.root = Builder.load_file('app.kv')
        self.song_list.load_songs()
        self.song_list.sort('Artist')
        self.building_widgets()
        self.right_widgets()
        return self.root

    def building_widgets(self):
        """
            left layout creation base on widgets created in an order
        """
        self.root.ids.leftLayout.add_widget(self.sort_label)
        self.root.ids.leftLayout.add_widget(self.spinner)
        self.root.ids.leftLayout.add_widget(self.add_song_label)
        self.root.ids.leftLayout.add_widget(self.title_label)
        self.root.ids.leftLayout.add_widget(self.title_text_input)
        self.root.ids.leftLayout.add_widget(self.artist_label)
        self.root.ids.leftLayout.add_widget(self.artist_text_input)
        self.root.ids.leftLayout.add_widget(self.year_label)
        self.root.ids.leftLayout.add_widget(self.year_text_input)
        self.root.ids.leftLayout.add_widget(self.add_song_button)
        self.root.ids.leftLayout.add_widget(self.clear_button)
        self.root.ids.topLayout.add_widget(self.top_label)

        # Setting on click for sorting spinner, add button and clear button
        self.spinner.bind(text=self.songs_sort)
        self.add_song_button.bind(on_release=self.add_song_handler)
        self.clear_button.bind(on_release=self.clear_fields)

    def right_widgets(self):
        """
            Building right layout with widgets based on the list we created.
        """
        # Sets the count label
        self.top_label.text = "To Learn: " + str(
            self.song_list.get_required_songs_count()) + ". Learned: " + str(
                self.song_list.get_learned_songs_count())

        # Goes through each song in the list and check if it learned or required and setts color based on that
        for song in self.song_list.songs:
            # n = Learned
            if song[0].status == 'n':
                song_button = Button(text='"' + song[0].title + '"' + " by " +
                                     song[0].artist + " (" +
                                     str(song[0].year) + ") "
                                     "(Learned)",
                                     id=song[0].title)

                song_button.background_color = [88, 89, 0, 0.3]
            # y = required to learn
            else:
                song_button = Button(text='"' + song[0].title + '"' + " by " +
                                     song[0].artist + " (" +
                                     str(song[0].year) + ")",
                                     id=song[0].title)

                song_button.background_color = [0, 88, 88, 0.3]

            # Setting on click for the buttons created
            song_button.bind(on_release=self.click_handler)
            self.root.ids.rightLayout.add_widget(song_button)

    def click_handler(self, button):
        """
            Handles on click for each song button created
        """

        # if button user clicked is learned change it to required to learn and update the status bar
        if self.song_list.get_song(button.id).status == 'n':
            self.song_list.get_song(button.id).status = 'y'
            self.root.ids.bottomLayout.text = "You need to learn " + str(
                self.song_list.get_song(button.id).title)

        # if button user clicked is Required to learn change it to learned and update the status bar
        else:
            self.song_list.get_song(button.id).status = 'n'
            self.root.ids.bottomLayout.text = "You have learned " + str(
                self.song_list.get_song(button.id).title)

        # Update the sorting and reloads the right layout
        self.songs_sort()
        self.root.ids.rightLayout.clear_widgets()
        self.right_widgets()

    def clear_fields(self, *args):
        """
            Handles clearing up all the text fields and status bar
        """
        self.title_text_input.text = ""
        self.artist_text_input.text = ""
        self.year_text_input.text = ""
        self.root.ids.bottomLayout.text = ""

    def add_song_handler(self, *args):
        """
            This method handles all the error checking for user input on text field and creates a Song object
        """
        # Checks if all the input fields are complete if not error text will be displayed
        if str(self.title_text_input.text).strip() == '' or str(
                self.artist_text_input.text).strip() == '' or str(
                    self.year_text_input.text).strip() == '':
            self.root.ids.bottomLayout.text = "All fields must be completed"
        else:
            try:
                # If year is negative
                if int(self.year_text_input.text) < 0:
                    self.root.ids.bottomLayout.text = "Please enter a valid number"
                # If all the criteria matches it creates a Song object in song_list class
                else:
                    self.song_list.add_song(self.title_text_input.text,
                                            self.artist_text_input.text,
                                            int(self.year_text_input.text))
                    self.song_list.sort(self.spinner.text)
                    self.clear_fields()
                    self.root.ids.rightLayout.clear_widgets()
                    self.right_widgets()
            # String Error checking for year input
            except ValueError:
                self.root.ids.bottomLayout.text = "Please enter a valid number"

    def stop(self):
        # By closing, all the data form the list will be saved to to songs.csv file
        self.song_list.save_file()
Beispiel #17
0
"""
(incomplete) Tests for SongList class
"""
from songlist import SongList
from song import Song

# test empty SongList
song_list = SongList()
print(song_list.songs)
assert len(song_list.songs) == 0

# test loading songs
song_list.load_songs('songs.csv')
print(song_list.songs)
assert len(song_list.songs) > 0  # assuming CSV file is not empty

# TODO: add tests below to show the various required methods work as expected
# test sorting songs
song_list.sort_songs()
print(song_list.songs)
for i in range(len(song_list.songs)):
    print(song_list.songs[i])
# check manually if the list is ordered by artist or not (default)

# test adding a new Song
song_list.add_songs("Sugar", "Maroon 5", 2017)
song_list.sort_songs()
print(song_list.songs[0])
# The new song should be on top of the list (A, A, 1, True)
# As it has been added and sort by artist (default)
Beispiel #18
0
class SongsToLearnApp(App):
    # Used for sorting
    current_state = StringProperty()
    sort_codes = ListProperty()

    def build(self):
        self.title = "Song List"
        self.root = Builder.load_file('app.kv')
        # Used to identify which song button is pressed
        # self.song_button_id = []
        # using the SongList Class
        self.song_list = SongList()
        self.song_list.load_songs("songs.csv")
        self.create_song_list()
        # Used for sorting
        self.sort_codes = SORT_TYPE.keys()
        self.current_state = self.sort_codes[0]
        # Button variable for the learning of songs
        return self.root

    # Create the buttons based on the length of the song list
    def create_song_list(self):
        # # Clear all in order to remake
        # if not self.song_button_id:
        #     self.song_button_id.clear()
        self.root.ids.songs.clear_widgets()
        self.root.ids.req_learn.text = self.song_list.cal_learn_n_req()
        for i in range(len(self.song_list.songs)):
            # All the attributes of the button
            song_text = str(self.song_list.songs[i].__str__())
            button2 = Button(text=song_text,
                             font_size=15,
                             text_size=(200, None))
            # button2.font_size = 15
            # button2.text_size = (200, None)
            if self.song_list.songs[i].is_required:
                button2.background_color = 0.0, 1.0, 0.0, 1.0
                button2.state = 'down'
            else:
                button2.background_color = 1.0, 0.0, 0.0, 1.0
            # Bind the Button to the function handle_song_learn()
            # button2.bind(on_release=lambda x: self.handle_song_learn(button2))
            button2.bind(on_release=self.handle_song_learn)
            # This line makes the buttons
            self.root.ids.songs.add_widget(button2)
            # # Save the buttons ids
            # self.song_button_id.append(button.ids)

    # Used to sort my list of songs (it destroys and recreates all the buttons)
    def handle_sort(self, current_state):
        if current_state == "Year":
            self.song_list.sort(1)
            self.create_song_list()
        elif current_state == "Title":
            self.song_list.sort(2)
            self.create_song_list()
        elif current_state == "Artist":
            self.song_list.sort(3)
            self.create_song_list()

    # Handles learning songs
    def handle_song_learn(self, check_button):
        for i in range(len(self.song_list.songs)):
            if check_button.text == str(self.song_list.songs[i].__str__()):
                if self.song_list.songs[i].is_required:
                    # Already learned
                    self.root.ids.message_id.text = self.song_list.songs[
                        i].title + "\nis already learned"
                    self.create_song_list()
                else:
                    # Change to learned
                    self.root.ids.message_id.text = self.song_list.songs[
                        i].title + "\nis now learned"
                    self.song_list.songs[i].is_required = True
                    self.create_song_list()
                    self.song_list.save_songs()

    # Used to add a song to the list of songs (forces a sort)
    def handle_add_song(self):
        if self.root.ids.input_title.text == '':
            self.root.ids.input_title.text = "All fields must be completed"
        if self.root.ids.input_artist.text == '':
            self.root.ids.input_artist.text = "All fields must be completed"
        if self.root.ids.input_year.text.isdigit() == False:
            self.root.ids.input_year.text = "Please enter a valid number"
            return
        elif int(self.root.ids.input_year.text) <= 1:
            self.root.ids.input_year.text = "Please enter a valid number"
            return
        if self.root.ids.input_title.text != '' and self.root.ids.input_artist.text != '' and int(
                self.root.ids.input_year.text
        ) > 1 and self.root.ids.input_year.text.isdigit():
            self.song_list.add_song(self.root.ids.input_title.text,
                                    self.root.ids.input_artist.text,
                                    int(self.root.ids.input_year.text))
            self.root.ids.message_id.text = "You have learned " + self.root.ids.input_title.text
            # Recreate the list to add the new song
            self.create_song_list()
            # Forces a sort to ensure the list will be sorted
            self.handle_sort(self.current_state)
            # Save the new song to the CSV
            self.song_list.save_songs()

    # Clears all text in the input fields and the status bar
    def handle_clear(self):
        self.root.ids.message_id.text = ""
        self.root.ids.input_artist.text = ""
        self.root.ids.input_title.text = ""
        self.root.ids.input_year.text = ""
Beispiel #19
0
class SongsToLearnApp(App):
    message = StringProperty()
    message2 = StringProperty()
    current_state = StringProperty()
    sort_by = ListProperty()

    def __init__(self, **kwargs):
        """
        construct the main app
        """
        super(SongsToLearnApp, self).__init__(**kwargs)
        self.sort_by = ["Title", "Artist", "Year", "Is_required"]# Create a list for "spinner"
        self.current_state = self.sort_by[0]# Set the "Title" as the default option
        self.song_list = SongList()
        self.song_list.load_songs()

    def build(self):
        """
        Build the Kivy GUI
        :return: reference to the root Kivy widget
        """
        self.title = "Songs to learn 2.0 by PengJie"
        self.root = Builder.load_file('app.kv')
        self.create_widgets()
        return self.root

    def change_sort(self):
        self.song_list.sort_songs.sort(self)

    def press_clear(self):
        # Clean the all the inputs
        self.root.ids.title.text = ''
        self.root.ids.artist.text = ''
        self.root.ids.year.text = ''

    def create_widgets(self):
        """
        Create widgets to show the song list
        """
        num_song = len(self.song_list.list_songs)
        learned_song = 0# Set the 0 to the number of songs learned
        for song in self.song_list.list_songs:# create a button for each data entry, specifying the text and id
            title = song.title
            artist = song.artist
            year = song.year
            learned = song.is_required
            display_text = self.formatText(title, artist, year, learned)# Display what should be added to the widget
            if learned == "n":
                learned_song += 1
                button_color = [0.7, 1, 0, 1]# If the song is learned,display green button
            else:
                button_color = [255, 0, 0, 1]  # If the song is not learned, display red button
            #If users click a song, the song will be learned
            temp_button = Button(text=display_text, id=song.title, background_color=button_color)
            temp_button.bind(on_release=self.press_entry)# The message2 will display that the song is learned
            self.root.ids.entriesBox.add_widget(temp_button)
        self.message = "To learn: {}. Learned: {}".format(num_song - learned_song, learned_song)# Display number of songs learned and not learned

    def formatText(self, title, artist, year, learned):
        """
        Format the text displayed in the messages2
        """
        if learned == "n":
            display_text = "{} by {} ({}) (Learned)".format(title, artist, year)
        else:
            display_text = "{} by {} ({})".format(title, artist, year)
        return display_text


    def press_entry(self, button):
        """
        The text displays in the message2
        :param instance: the Kivy button instance
        :return: None
        """
        buttonText = button.text #Determine the text on the widget buttons
        selectedSong = Song()
        for song in self.song_list.list_songs:
            displaymessage = self.formatText(song.title, song.artist, song.year, song.is_required)
            if buttonText == displaymessage:
                selectedSong = song
                break
        selectedSong.mark_learned()  # Mark the song learned
        self.root.ids.entriesBox.clear_widgets()
        self.create_widgets()
        self.message2 = "You have learned {}".format(selectedSong.title)#Display the song you have learned

    def add_songs(self):
        """
        Users add song to the song list
        """
        #Check whether users input empty information
        if self.root.ids.title.text == "" or self.root.ids.artist.text == "" or self.root.ids.year.text == "":
            self.message2 = "The field can not be blank"
        try:
            # check whether users input valid information
            is_required = "y"
            title = str(self.root.ids.title.text)
            artist = str(self.root.ids.artist.text)
            year = int(self.root.ids.year.text)
            # Add the song inputted to the song list
            self.song_list.add_to_list(title, artist, year, is_required)
            temp_button = Button(text=self.formatText(title, artist, year, is_required))
            temp_button.bind(on_release=self.press_entry)
            self.root.ids.entriesBox.add_widget(temp_button)
            # Empty the inputs after adding the song
            self.root.ids.title.text = ""
            self.root.ids.artist.text = ""
            self.root.ids.year.text = ""
        except ValueError:
            self.message2 = "Please enter a valid number"
 def __init__(self, **kwargs):
     super().__init__(**kwargs)
     self.song_list = SongList()
     self.requireSong = 0
     self.learnedSong = 0
class SongsToLearnApp(App):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.song_list = SongList()
        self.requireSong = 0
        self.learnedSong = 0

    def build(self):
        self.title = "Song To learn 2.0"  # Add the title of the program
        self.root = Builder.load_file('app.kv')  # Reference kivy file
        self.song_list.load_song()  # Using class method to load CSV
        self.show_song()
        self.sorting(self.root.ids.sort_option.text)
        return self.root

    def show_song(self):  # Display Songs in GUI
        self.requireSong = 0
        self.learnedSong = 0
        for i in self.song_list.song:
            if i.require == 'y':  # y means need to learn song
                song_button = Button(
                    text='' + '"' + i.title + '"' + " by " + i.artist + " (" +
                    i.year + ")",
                    id=i.title)  # Display format for need to learn song
                song_button.background_color = [88, 89, 0, 0.3
                                                ]  # Button background colour
                self.requireSong += 1
            else:
                song_button = Button(
                    text='' + '"' + i.title + '"' + " by " + i.artist + " (" +
                    i.year + ") (learned)",
                    id=i.title)  # Display format for learned song
                song_button.background_color = [0, 88, 88, 0.3
                                                ]  # Button background colour
                self.learnedSong += 1
            song_button.bind(on_release=self.select)
            self.root.ids.all_song.add_widget(song_button)
            # Display learned and to learn song
            self.root.ids.title_learned.text = "To learn: {}, Learned: {}".format(
                self.requireSong, self.learnedSong)

    def select(self, button):  # Display selected song
        if self.song_list.get_song(
                button.id).require == 'y':  # Mark song as learned
            self.song_list.get_song(button.id).require = 'n'
            self.root.ids.program_detail.text = "{} is learned.".format(
                button.id)
        else:
            self.song_list.get_song(
                button.id).require = 'y'  # Mark song as unlearn
            self.root.ids.program_detail.text = "{} need to learn.".format(
                button.id)  # Display selected song format
        self.root.ids.program_detail.color = ANNOUNCEMENT  # Set label colour
        self.sorting(self.root.ids.sort_option.text)
        self.root.ids.all_song.clear_widgets()  # Clear widgets
        self.show_song()

    def sorting(self, chosen):  # Sort song function
        available_choice = chosen
        if available_choice == 'Title':  # Sort the song by Title
            self.song_list.sort(0)
        elif available_choice == 'Artist':  # Sort the song by Artist
            self.song_list.sort(1)
        elif available_choice == 'Year':  # Sort the song by Year
            self.song_list.sort(2)
        else:
            self.song_list.sort(3)  # Sort the song by Require
        self.root.ids.sort_option.clear_widgets()
        self.root.ids.all_song.clear_widgets()
        self.show_song()

    def add_song(self):  # Add new song to the list
        title = self.root.ids.title_fill.text
        artist = self.root.ids.artist_fill.text
        year = self.year_check()
        if title == '' or artist == '' or year == '':  # No input validation
            self.root.ids.program_detail.color = ERROR_COLOUR
            self.root.ids.program_detail.text = 'Please fill every box'
        elif year == "string":  # Year validation
            self.root.ids.program_detail.color = ERROR_COLOUR
            self.root.ids.program_detail.text = 'Year must be an integer'
        elif year < 0:  # Year validation
            self.root.ids.program_detail.color = ERROR_COLOUR
            self.root.ids.program_detail.text = 'Year must have at least 4 digits'
        else:
            song_title = self.root.ids.title_fill.text
            song_artist = self.root.ids.artist_fill.text
            song_year = self.root.ids.year_fill.text
            song_input = Song(song_title, song_artist, song_year, 'y')
            self.song_list.add_song(song_input)  # Add new song to song list
            self.root.ids.all_song.clear_widgets()
            self.clear_all()
            self.root.ids.program_detail.color = ANNOUNCEMENT
            self.root.ids.program_detail.text = 'A song have added to the song list'
            self.show_song()

    def year_check(self):  # Validate the song year input
        try:
            year = int(self.root.ids.year_fill.text)
            return year
        except ValueError:
            year = 'string'
            return year

    def clear_all(self):  # Clear input in text input function
        self.root.ids.title_fill.text = ''
        self.root.ids.artist_fill.text = ''
        self.root.ids.year_fill.text = ''
        self.root.ids.program_detail.text = ''

    def stop(self):
        self.song_list.save_song(
        )  # Update CSV file after the user close the program
Beispiel #22
0
"""
(incomplete) Tests for SongList class
"""
from songlist import SongList
from song import Song

# test empty SongList
song_list = SongList()
print(song_list)
assert len(song_list.songs) == 0

# test loading songs
song_list.load_songs('songs.csv')
print(song_list)
assert len(song_list.songs) > 0  # assuming CSV file is not empty

# TODO: add tests below to show the various required methods work as expected
# test sorting songs
song_list.sort_songs()
# test adding a new Song
song_list.add_song()
# test get_song()
song_list.get_song()
print(song_list)
# test getting the number of required and learned songs (separately)
# test saving songs (check CSV file manually to see results)
song_list.save_songs()
Beispiel #23
0
"""
(incomplete) Tests for SongList class
"""
from songlist import SongList
from song import Song

# test empty SongList
song_list = SongList()
print(song_list)
assert len(song_list.songs) == 0

# test loading songs
song_list.load_songs('songs.csv')
print(song_list)
assert len(song_list.songs) > 0  # assuming CSV file is not empty

# TODO: add tests below to show the various required methods work as expected
# test sorting songs
# """Sort by Year"""
# song_list.sort(1)
# print("Year Sort")
# print(song_list)
# """Sort by Title"""
# song_list.sort(2)
# print("Title Sort")
# print(song_list)
# """Sort by Artist"""
# song_list.sort(3)
# print("Artist Sort")
# print(song_list)
Beispiel #24
0
class Song_To_LearnApp(App):
    # The string for main status will be change
    # depend on the function runs
    main_status = StringProperty()
    # The string the update when new song added or new song learnt
    learn_status = StringProperty()

    # Initializer and start to load songs from the file
    def __init__(self, **kwargs):
        super(Song_To_LearnApp, self).__init__(**kwargs)
        self.album = SongList()
        self.album.load_songs("songs.csv")
        self.album.kivy_load_songs()

    def count_status(self):
        self.learn_status = self.album.get_status_songs()

    # GUI BUILDER
    def build(self):
        Window.clearcolor = (1, 1, 1, 1)
        self.title = "Song to learn v2.0 by Nhan Gia Huy"
        self.root = Builder.load_file("app.kv")
        # Create the album
        self.create_album()
        # Trigger learn status
        self.count_status()
        # Welcome user
        self.main_status = "Welcome to Song To Learn App"
        return self.root

    def on_stop(self):
        self.album.save_songs()

    # Generating an album based on the song list
    def create_album(self):
        # For every song in the list
        for song in self.album.review_list:
            # If it is learned, make the button background black
            if song.split(",")[1] == "learned":
                temp_text = "{} ({})".format(
                    song.split(",")[0],
                    song.split(",")[1])
                temp_button = Button(text=temp_text,
                                     background_color=(0, 0, 0, 1))
            # Else, make a button with a background of grey
            else:
                # Create a text for the button to help the user know the song
                temp_text = "{}".format(song.split(",")[0])
                # give the song title as an ID of the  button
                temp_id = song.split(",")[-1]
                # Create a button
                temp_button = Button(id=temp_id, text=temp_text)
                # bind the function to the button
                # when pressed, this will marked the song as learnt
                temp_button.bind(on_release=self.press_learnt)
            # Add the button the the box
            self.root.ids.list_of_songs.add_widget(temp_button)

    # Function when the button pressed, unlearn song return as learnt
    def press_learnt(self, instance):
        # When pressed, the selected button will throw its ID to the get song
        self.album.get_songs(instance.id).mark_learned()
        # recreate the list
        self.root.ids.list_of_songs.clear_widgets()
        self.album.kivy_load_songs()
        self.create_album()
        # Update status bar
        self.main_status = "{} has been marked as learnt".format(instance.text)
        # update learn status
        self.count_status()

    # Create a attribute for sorting radio button
    # default setup for the radio button (default will be sort by artist)
    Artist = ObjectProperty(True)
    Title = ObjectProperty(False)
    Year = ObjectProperty(False)

    #  sorting songs based on radio buttons
    def radio_button_sort(self, option):
        # Sort the song based on the option
        self.album.sort_songs(option=option)
        # Recreate list for GUI
        self.album.kivy_load_songs()
        # Destroy the whole list and recreate it with new order (sorted)
        self.root.ids.list_of_songs.clear_widgets()
        self.create_album()
        # Update status bar
        self.main_status = "Sorting by {}".format(option)

    # function to open the popup for adding purpose
    def open_adding_pop_up(self):
        self.root.ids.Adding_Popup.open()
        # Update status bar
        self.main_status = "Adding new song"

    # Function to dismiss the popup
    def press_cancel_pop_up(self):
        # Dismiss the pop up
        self.root.ids.Adding_Popup.dismiss()
        # Update count learn song
        self.count_status()

    # Handle add function
    def press_add(self):
        # gather information for new song
        title = self.get_title()
        year = self.get_year()
        artist = self.get_artist()
        # check the information
        # Title is blank => Prompt title shouldnt be blank
        if title == "" or title == " ":
            self.root.ids.add_prompt_3.text = "Title cannot be blank"
        # artist is blank => Prompt artist shouldnt be blank
        elif artist == "" or artist == " ":
            self.root.ids.add_prompt_3.text = "Artist cannot be blank"
        # Year is blank => Prompt artist shouldnt be blank
        elif year == "" or year == " ":
            self.root.ids.add_prompt_3.text = "Year cannot be blank"
        # If year get return as -1, There is a Value Error, Prompt the Error
        elif year == "Case value":
            self.root.ids.add_prompt_3.text = "Invalid input for year. Try again"
        # If the year is unreal, prompt the user to input again
        elif year == "Case 2019":
            self.root.ids.add_prompt_3.text = "The year is unreal, must be =< 2019"
        # If year is negative, Prompt year must be > 0
        elif year < 0:
            self.root.ids.add_prompt_3.text = "The year must be > 0"
        else:
            # add new song to the list
            self.album.add_songs(title, artist, year)
            # clear and recreate the list
            self.root.ids.list_of_songs.clear_widgets()
            self.album.kivy_load_songs()
            self.create_album()
            # close popup
            self.root.ids.Adding_Popup.dismiss()
            # Update status bar
            self.main_status = "{} by {} ({}) has been added".format(
                title, artist, year)
            # update learn status
            self.count_status()

    # Method to gather the information in the text input box
    def get_title(self):
        # retrieve value and return value
        value = str(self.root.ids.add_detail_title.text).title()
        return value

    def get_artist(self):
        # retrieve value and return value
        value = str(self.root.ids.add_detail_artist.text).title()
        return value

    def get_year(self):
        # retrieve value and return value
        try:
            value = int(self.root.ids.add_detail_year.text)
            if value > 2019:
                return "Case 2019"
            else:
                return value
        # return Case value for case where input is a Value Error
        except ValueError:
            return "Case value"
Beispiel #25
0
class SongsToLearnApp(App):

    current_selection = StringProperty()
    spinner_menu = ListProperty()
    songs = SongList()
    song = Song()
    song_id_list = []

    def build(self):
        SongList()  # initialise an empty list on program start
        Window.size = (900, 600)
        self.title = 'Songs to Learn 2.0'
        self.root = Builder.load_file('app.kv')
        songs_list = self.load_songs()
        self.create_entry_grids(songs_list)
        self.root.ids.message_box.text = '~~~Welcome to Songs to Learn 2.0~~~'

        return self.root

    def create_entry_grids(self, input_list):
        self.clear_widget()
        for song in input_list:
            if song.learned == True:
                learn_state = '(Learned)'
                btn_color = (0, 1, 0, 1)
            else:
                learn_state = ''
                btn_color = (1, 0, 0, 1)
            btn_id = '{}_{}'.format(song.title, song.year)
            temp_button = Button(id=btn_id,
                                 background_color=btn_color,
                                 text='{} by {} ({}) {}'.format(
                                     song.title, song.artist, song.year,
                                     learn_state))
            self.root.ids.song_count.add_widget(temp_button)
            self.song_id_list.append(temp_button)
            temp_button.bind(on_release=self.handle_mark)
        self.song_status()

    def handle_clear(self):
        # Clears the text input fields to empty
        self.root.ids.input_title.text = ''
        self.root.ids.input_artist.text = ''
        self.root.ids.input_year.text = ''

    def handle_add(self):
        """Validates input, and passes the inputs to the function to create a new song object"""
        song_title = self.root.ids.input_title.text
        song_artist = self.root.ids.input_artist.text
        song_year = self.root.ids.input_year.text
        err_check = self.error_check()

        if err_check == 'Blank':
            self.root.ids.message_box.color = (1, 0, 0, 1)
            self.root.ids.message_box.text = 'ERROR: All fields must be completed'
            self.root.ids.btn_add.background_color = (1, 0, 0, 1)
        elif err_check == 'Invalid':
            self.root.ids.message_box.color = (1, 0, 0, 1)
            self.root.ids.message_box.text = 'WARNING: Year Invalid. Please enter Valid year (1800 to 2018)'
            self.root.ids.btn_add.background_color = (1, 0, 0, 1)
        elif err_check == 'Type':
            self.root.ids.message_box.color = (1, 0, 0, 1)
            self.root.ids.message_box.text = 'WARNING: Error in Field "Year". Please Check Input'
            self.root.ids.btn_add.background_color = (1, 0, 0, 1)
        elif err_check == 'Duplicate':
            self.root.ids.message_box.color = (1, 0, 0, 1)
            self.root.ids.message_box.text = '{} by {} already exists'.format(
                song_title, song_artist)
            self.root.ids.btn_add.background_color = (1, 0, 0, 1)
        else:
            send_input = Song(song_title, song_artist, song_year, False)
            # Registers the song attribute given by the user, with additional attribute 'learned' automatically set to False
            added_list = self.songs.add_songs(send_input)
            self.make_entries(added_list)
            self.root.ids.message_box.color = (1, 1, 1, 1)
            self.root.ids.message_box.text = 'You added {} by {}'.format(
                song_title, song_artist)
            self.root.ids.btn_add.background_color = (0, 0, 1, 1)

    def handle_sort_change(self, spinner_choice):
        self.clear_widget()
        sort_attr = spinner_choice
        if sort_attr == 'Title':
            sorted_list = self.songs.sort_songs(0)
        elif sort_attr == 'Artist':
            sorted_list = self.songs.sort_songs(1)
        elif sort_attr == 'Year':
            sorted_list = self.songs.sort_songs(2)
        self.make_entries(sorted_list)
        self.root.ids.message_box.text = 'Sorted by {}'.format(sort_attr)

    def load_songs(self):
        sort_list = self.songs.load_songs('songs.csv')
        return sort_list

    def song_status(self):
        learn = self.songs.calculate_song_learned()
        not_learn = self.songs.calculate_song_not_learned()
        total_songs = learn + not_learn
        status_text = 'Total Songs: {} -- To learn: {} -- Learned: {}'.format(
            total_songs, learn, not_learn)
        self.root.ids.status_bar.text = status_text

    def make_entries(self, input_list):
        self.clear_widget()
        for song in input_list:
            if song.learned == True:
                learn_state = '(Learned)'
                btn_color = (0, 1, 0, 1)
            else:
                learn_state = ''
                btn_color = (1, 0, 0, 1)
            btn_id = '{}_{}'.format(song.title, song.year)
            temp_button = Button(id=btn_id,
                                 background_color=btn_color,
                                 text='{} by {} ({}) {}'.format(
                                     song.title, song.artist, song.year,
                                     learn_state))
            self.song_id_list.append(temp_button)
            self.root.ids.song_count.add_widget(temp_button)
            temp_button.bind(on_release=self.handle_mark)
        self.song_status()

    def handle_mark(self, instance):
        btn = instance.id
        for song in self.songs.song_list:
            validate = '{}_{}'.format(song.title, song.year)
            if btn == validate:
                if song.learned == True:
                    self.root.ids.message_box.text = 'You have already learned {} ({})'.format(
                        song.title, song.year)
                else:
                    self.songs.mark_as_learned(btn)
                    self.root.ids.message_box.text = (
                        'You learned {} ({})'.format(song.title, song.year))
        give_list = self.songs.give_songs()
        self.make_entries(give_list)

    def exit_app(self):
        self.songs.save_songs()

    def clear_widget(self):
        for song_id in self.song_id_list:
            self.root.ids.song_count.remove_widget(song_id)

    def error_check(self):
        title_check = self.root.ids.input_title.text
        artist_check = self.root.ids.input_artist.text
        year_check = self.root.ids.input_year.text
        error_state = ''
        if title_check == '' or artist_check == '' or year_check == '':
            error_state = 'Blank'
        else:
            try:
                int(year_check)
            except ValueError:
                error_state = 'Type'
            else:
                if int(year_check) > 2018 or int(year_check) < 1800:
                    error_state = 'Invalid'
        for song in self.songs.song_list:
            if title_check == song.title and artist_check == song.artist and year_check == song.year:
                error_state = 'Duplicate'
        return error_state

    def handle_stop(self):
        self.songs.save_songs()
        sys.exit(0)
"""
(incomplete) Tests for SongList class
"""
from songlist import SongList
from song import Song

# test empty SongList
song_list = SongList()
print(song_list)
assert len(song_list.song) == 0

# test loading songs
song_list.load_song()
print(song_list)
assert len(song_list.song) > 0  # assuming CSV file is not empty

# TODO: add tests below to show the various required methods work as expected
# test sorting songs
print("Sorting by year")
assert song_list.sort('year')
print("Sorting by title")
assert song_list.sort('title')

# test adding a new Song
song3 = Song('Hero', 'Enrique Iglesias', 2008, 'y')
assert song_list.add_song(song3)

# test get_song()
assert song_list.get_song('Hero')

# test getting the number of required and learned songs (separately)
Beispiel #27
0
""" Tests for SongList class
"""
from songlist import SongList
from song import Song

# test empty SongList
song_list = SongList()
print(song_list)
assert len(song_list.list_songs) == 0

# test loading songs
song_list.load_songs()
print(song_list.list_songs)
assert len(song_list.list_songs) == 6
print(song_list)
assert len(song_list.list_songs) > 0  # assuming CSV file is not empty
q
# test sorting songs
song_list.sort("title")


# test adding a new Song
song_list.add_to_list(Song("21 Guns", "Green Day", "2006", "y"))
print(song_list)


# test getting the number of required and learned songs (separately)


# test saving songs (check CSV file manually to see results)
Beispiel #28
0
"""
Tests each method of the SongList class showing how each one works at an individual level
"""
from songlist import SongList
from song import Song

song = Song("Amazing Grace", "John Newton", 1779, True)

# test empty SongList
song_list = SongList()
print(song_list)
assert len(song_list.songs) == 0

# test loading songs
song_list.load_songs('songs.csv')
print("Loaded SongList: \n{}".format(song_list))
assert len(song_list.songs) > 0  # assuming CSV file is not empty

# test sorting songs
print("----Testing sort----")
print("Unsorted SongList is:\n{}".format(song_list))
song_list.sort_songs("required")
print("Sorted SongList by learned or not then title is:\n{}".format(song_list))

# test adding a new Song
print("----Testing add_song----")
print("Adding {} to SongList".format(song))
song_list.add_song(song)
print("Updated SongList is: \n\n{}".format(song_list))

# test get_song_by_title()
Beispiel #29
0
class SongsToLearnApp(App):  # Class refering to the Kivy app
    """

    Main program:
    Display a list of songs in a GUI model using Kivy app

    """

    message = StringProperty()  # Define first status text
    message2 = StringProperty()  # Define second status text
    current_sort = StringProperty()  # Define current sorting of song list
    sort_choices = ListProperty()  # Define sorting options of song list

    def __init__(self, **kwargs):
        """
        Initiate song_list to SongList class
        Initiate sort_choices as an array
        Initiate the current sorting option as "title"
        Initiate the function load_songs to load csv file
        :param kwargs:
        returns None
        """
        super(SongsToLearnApp, self).__init__(**kwargs)
        self.song_list = SongList()
        self.sort_choices = ["title", "artist", "year", "is_required"]
        self.current_sort = self.sort_choices[0]
        self.song_list.load_songs()

    def build(self):
        """
        Build the Kivy GUI
        :return: widgets of the GUI
        """
        self.learn___ = "Songs to learn 2.0"  # Name the GUI's name
        self.title = self.learn___
        self.root = Builder.load_file('app.kv')  # Connect to Kivy app
        self.create_widgets()  # Create widgets in Kivy GUI
        return self.root

    def change_sort(self, sorting_choice):
        """
        Function to change the sorting of the song list
        :param sorting_choice: Based on what choice the user selects, the song list will be sorted that way
        :return: sorted song list
        """
        self.message = "song have been sorted by: {}".format(sorting_choice)
        self.song_list.sort(sorting_choice)
        self.root.ids.entriesBox.clear_widgets()
        self.create_widgets()
        sort_index = self.sort_choices.index(sorting_choice)
        self.current_sort = self.sort_choices[sort_index]

    def blank(self):
        """
        Clear all inputs after clicking the Clear button
        :return: blanks at inputs
        """
        self.root.ids.song_title.text = ''  # Empty the song title input
        self.root.ids.song_artist.text = ''  # Empty the song artist input
        self.root.ids.song_year.text = ''  # Empty the song year input

    def create_widgets(self):
        """
        Create widgets that lists the songs from the csv file
        :return: song list widgets
        """
        num_song = len(self.song_list.list_songs
                       )  # Determine the number of songs in the list
        learned_song = 0  # Initial number of learned song is 0
        for song in self.song_list.list_songs:  # Loop from the first song to the last song within the song list

            title = song.title  # Dim the title of each song
            artist = song.artist  # Dim the artist of each song
            year = song.year  # Dim the year of each song
            learned = song.is_required  # Dim the need for the song to either be learned or not learned
            display_text = self.generateDisplayText(
                title, artist, year,
                learned)  # display what should be added to the widget

            if learned == "n":
                # Condition when the song is learned, count the number of learned songs and format their background color (Velvet)

                learned_song += 1
                button_color = self.getColor(learned)
            else:
                button_color = self.getColor(
                    learned)  # If the song is not learned, display Blue color

            # By clicking a song, that song will be learned
            temp_button = Button(
                text=display_text,
                id=song.title,
                background_color=button_color)  # Mark the song learned
            temp_button.bind(on_release=self.press_entry
                             )  # Display the message of the GUI status

            self.root.ids.entriesBox.add_widget(
                temp_button)  # Apply to the Kivy app
        self.message = "To learn: {}. Learned: {}".format(
            num_song - learned_song, learned_song)
        # Display number of songs learned and not learned

    def generateDisplayText(
            self, title, artist, year,
            learned):  #Formating any text displayed in the messages
        if learned == "n":
            display_text = "{} by {} ({}) (Learned)".format(
                title, artist, year)
        else:
            display_text = "{} by {} ({})".format(title, artist, year)

        return display_text

    def getColor(self, learned):  #Display colors of the song widgets
        if learned == "n":
            button_color = [1, 0, 0, 1]
        else:
            button_color = [0, 0, 1, 1]
        return button_color

    def press_entry(self, button):  #Function that displays the 2nd message
        buttonText = button.text  #Determine the text on the widget buttons
        selectedSong = Song()
        for song in self.song_list.list_songs:
            #Loop the songs within the song list

            songDisplayText = self.generateDisplayText(song.title, song.artist,
                                                       song.year,
                                                       song.is_required)
            #Display the text as formatted in generateDisplayText
            if buttonText == songDisplayText:
                selectedSong = song
                break

        selectedSong.mark_learned()  #Mark the song learned
        self.root.ids.entriesBox.clear_widgets()  #Apply to Kivy GUI
        self.create_widgets()

        self.message2 = "You have learned {}".format(
            selectedSong.title)  #Display whatever changed in message 2

    def add_songs(self):
        """
        Function allows user to add any song they want
        :return: Add the song inputted to the song list
        """

        #Check for empty inputs
        if self.root.ids.song_title.text == "" or self.root.ids.song_artist.text == "" or self.root.ids.song_year.text == "":
            self.root.ids.status2.text = "All fields must be completed"
            return
        try:
            #Define song items inputted
            song_title = str(self.root.ids.song_title.text)
            song_artist = str(self.root.ids.song_artist.text)
            song_year = int(self.root.ids.song_year.text)
            is_required = "y"

            #Add the song inputted to the song list
            self.song_list.add_to_list(song_title, song_artist, song_year,
                                       is_required)
            temp_button = Button(text=self.generateDisplayText(
                song_title, song_artist, song_year, is_required))
            temp_button.bind(on_release=self.press_entry)

            #Format the new song items
            temp_button.background_color = self.getColor(is_required)
            self.root.ids.entriesBox.add_widget(temp_button)

            #Empty the inputs after adding the song
            self.root.ids.song_title.text = ""
            self.root.ids.song_artist.text = ""
            self.root.ids.song_year.text = ""

        except ValueError:  #Display error when year input is not a number
            self.message2 = "Please enter a valid year"

    def on_stop(self):  #stop the GUI and save changes
        self.song_list.save_songs()
Beispiel #30
0
class SongsToLearnApp(App):
    """
    SongsToLearnApp
    Takes songs from songs.csv, stores them as objects and builds the GUI, the GUI's functions are:
    - Show # of completed songs & # of required songs
    - Shows songs in a sorted list with learned songs highlighted in green & un-learned songs highlighted in red
    - Show status messages to user
    - Allows user to change songs from learned to un-learned and vice versa
    - Allows user to add new songs to the list
    Upon exiting the App the updated song list is written to the specified file
    """
    current_sort_option = StringProperty()
    sort_options = ListProperty()

    def __init__(self, **kwargs):
        """
        Constructs App, sets self.songs to SongList class, sets self.song to Song class and loads the specified song
        file with self.songs.load_songs
        """
        self.songs = SongList()
        self.song = Song()
        self.songs.load_songs(FILE_NAME)
        super(SongsToLearnApp, self).__init__(**kwargs)

    def build(self):
        """
        Build Kivy GUI from file 'app.kv' with a default sorting option
        :return: root Kivy widget
        """
        self.title = "Songs To Learn 2.0"
        self.root = Builder.load_file('app.kv')
        self.sort_options = SORT_OPTIONS
        # Set default sorting option to 'Title' (first option in sorting list)
        self.current_sort_option = self.sort_options[0]
        self.create_widgets()
        return self.root

    def sort_songs(self, current_sort_option):
        """
        Sorts songs by current_sort_option, clears all widgets in the song box and then rebuilds them
        :param current_sort_option: method to sort songs by (options are "Title", "Artist", "Year" and "Required")
        :return: None
        """
        self.songs.sort_songs(current_sort_option)
        SongsToLearnApp.create_widgets(self)

    def clear_inputs(self):
        """
        Clears all text input fields
        :return: None
        """
        self.root.ids.input_title.text, self.root.ids.input_artist.text, self.root.ids.input_year.text = (
            "", "", "")

    def create_widgets(self):
        """
        Clears all widgets in the song box and then builds a widget in the song box for every song in the song list,
        learned songs are coloured green and required songs are coloured red. A label is assigned to show # of learned
        songs and # of required songs.
        :return:
        """
        self.root.ids.songsBox.clear_widgets()
        for song in self.songs.songs:
            temp_song_button = Button(text=str(song))
            # Ternary operator to determine button colour
            temp_song_button.background_color = RED if song.required else GREEN
            self.root.ids.songsBox.add_widget(temp_song_button)
            # On release of a temp_song_button, call change_learned_status method
            temp_song_button.bind(on_release=self.change_learned_status)
            self.root.ids.output_song_learned_status_label.text = "To learn: {}. Learned: {}".format(
                self.songs.get_number_of_required_songs(),
                self.songs.get_number_of_learned_songs())

    def change_learned_status(self, instance):
        """
        Changes a songs learned status from learned to required or vice versa depending on the songs current state, a
        label shows the changed status of the song and then the songs are sorted by the current sort option
        :param instance: Kivy button instance text
        :return: None
        """
        self.song = self.songs.get_song_by_title(instance.text)
        # Marks song as learned and shows according status text
        if self.song.required:
            self.song.mark_learned()
            status_text = "You have learned {}".format(self.song.title)
        # Marks song as required and shows according status text
        else:
            self.song.mark_required()
            status_text = "You need to learn {}".format(self.song.title)
        # Shows status text, sorts songs by current s
        self.root.ids.status_text.text = status_text
        self.sort_songs(self.root.ids.sort_options.text)

    def add_song(self):
        """
        Error checks text input fields on the release of Add Song button, if all error checks are passed song is added
        to the song list, all inputs are cleared and songs are sorted by the current sort option
        :return: Prevents function from going further if an error occurs
        """
        # Error check for blank inputs
        if "" in (self.root.ids.input_title.text,
                  self.root.ids.input_artist.text,
                  self.root.ids.input_year.text):
            self.root.ids.status_text.text = "All fields must be completed"
            return
        # Error check for negative numbers
        try:
            if int(self.root.ids.input_year.text) < 0:
                self.root.ids.status_text.text = "Year must be >= 0"
                return
        # Error check for invalid numbers
        except ValueError:
            self.root.ids.status_text.text = "Please enter a valid number"
            return
        # Song add, clear inputs, sort songlist
        song_to_add = Song(self.root.ids.input_title.text,
                           self.root.ids.input_artist.text,
                           int(self.root.ids.input_year.text))
        self.songs.add_song(song_to_add)
        SongsToLearnApp.clear_inputs(self)
        self.sort_songs(self.root.ids.sort_options.text)

    def on_stop(self):
        """
        Saves songs to specified file when app is closed
        :return: None
        """
        self.songs.save_songs(FILE_NAME)