Esempio n. 1
0
 def get_matched_row_list(self, key_column, search_criteria, case_sensitivity):
     search_proxy = QSortFilterProxyModel()
     search_proxy.setSourceModel(self.user_interface.tblLogData.model())
     search_proxy.setFilterCaseSensitivity(case_sensitivity)
     search_proxy.setFilterKeyColumn(key_column)
     if self.is_match_whole_word:
         search_criteria = r"\b{}\b".format(search_criteria)
         
     search_proxy.setFilterRegExp(search_criteria)
     matched_row_list = []
     for proxy_row in range(search_proxy.rowCount()):
         match_index = search_proxy.mapToSource(search_proxy.index(proxy_row, key_column))
         matched_row_list.append(match_index.row())
     self.search_criteria_updated = False    
     return matched_row_list
Esempio n. 2
0
 def set_sb_mapper_idx(self, usrn):
     """
     Use a proxy to find the mapper idx for the usrn
     :param usrn: USRN
     """
     model = self.mapper.model()
     # Create proxy
     search_proxy = QSortFilterProxyModel()
     search_proxy.setSourceModel(model)
     search_proxy.setDynamicSortFilter(True)
     search_proxy.setFilterKeyColumn(1)  # usrn col
     search_proxy.setFilterFixedString(str(usrn))
     # Assume only 1 record is in the filtered proxy
     source_idx = search_proxy.mapToSource(search_proxy.index(0, 0))
     source_row = source_idx.row()
     self.mapper.setCurrentIndex(source_row)
Esempio n. 3
0
    def get_matched_row_list(self, key_column, search_criteria,
                             case_sensitivity):
        search_proxy = QSortFilterProxyModel()
        search_proxy.setSourceModel(self.user_interface.tblLogData.model())
        search_proxy.setFilterCaseSensitivity(case_sensitivity)
        search_proxy.setFilterKeyColumn(key_column)
        if self.is_match_whole_word:
            search_criteria = r"\b{}\b".format(search_criteria)

        search_proxy.setFilterRegExp(search_criteria)
        matched_row_list = []
        for proxy_row in range(search_proxy.rowCount()):
            match_index = search_proxy.mapToSource(
                search_proxy.index(proxy_row, key_column))
            matched_row_list.append(match_index.row())
        self.search_criteria_updated = False
        return matched_row_list
Esempio n. 4
0
class TalkEditorApp(FreeseerApp):
    '''Freeseer talk database editor main gui class'''
    def __init__(self, config, db):
        super(TalkEditorApp, self).__init__(config)

        self.db = db

        icon = QIcon()
        icon.addPixmap(QPixmap(':/freeseer/logo.png'), QIcon.Normal, QIcon.Off)
        self.setWindowIcon(icon)
        self.resize(960, 600)

        #
        # Setup Layout
        #
        self.mainWidget = QWidget()
        self.mainLayout = QVBoxLayout()
        self.mainWidget.setLayout(self.mainLayout)
        self.setCentralWidget(self.mainWidget)
        self.mainLayout.setAlignment(Qt.AlignTop)

        # Add custom widgets
        self.commandButtons = CommandButtons()
        self.tableView = QTableView()
        self.tableView.setSortingEnabled(True)
        self.tableView.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.talkDetailsWidget = TalkDetailsWidget()
        self.importTalksWidget = ImportTalksWidget()
        self.newTalkWidget = NewTalkWidget()
        self.mainLayout.addWidget(self.importTalksWidget)
        #self.mainLayout.addLayout(self.titleLayout)
        self.mainLayout.addWidget(self.commandButtons)
        self.mainLayout.addWidget(self.tableView)
        self.mainLayout.addWidget(self.talkDetailsWidget)
        self.mainLayout.addWidget(self.importTalksWidget)
        # --- End Layout

        # Keep track of index of the most recently selected talk
        self.currentTalkIndex = QPersistentModelIndex()

        # Prompt user to "Continue Editing", "Discard Changes" or "Save Changes"
        self.savePromptBox = QMessageBox()
        self.savePromptBox.setWindowTitle("Unsaved Changes Exist")
        self.savePromptBox.setIcon(QMessageBox.Information)
        self.savePromptBox.setText(
            "The talk you were editing has unsaved changes.")
        self.continueButton = self.savePromptBox.addButton(
            "Continue Editing", QMessageBox.RejectRole)
        self.discardButton = self.savePromptBox.addButton(
            "Discard Changes", QMessageBox.DestructiveRole)
        self.saveButton = self.savePromptBox.addButton("Save Changes",
                                                       QMessageBox.AcceptRole)
        self.savePromptBox.setDefaultButton(self.saveButton)

        # Initialize geometry, to be used for restoring window positioning.
        self.geometry = None

        #
        # Setup Menubar
        #
        self.actionExportCsv = QAction(self)
        self.actionExportCsv.setObjectName('actionExportCsv')
        self.actionRemoveAll = QAction(self)
        self.actionRemoveAll.setObjectName('actionRemoveAll')

        # Actions
        self.menuFile.insertAction(self.actionExit, self.actionExportCsv)
        self.menuFile.insertAction(self.actionExit, self.actionRemoveAll)
        # --- End Menubar

        #
        # TableView Connections
        #
        self.connect(self.tableView, SIGNAL('activated(const QModelIndex)'),
                     self.click_talk)
        self.connect(self.tableView, SIGNAL('selected(const QModelIndex)'),
                     self.click_talk)
        self.connect(self.tableView, SIGNAL('clicked(const QModelIndex)'),
                     self.click_talk)

        # Import Widget
        self.connect(self.importTalksWidget.csvRadioButton,
                     SIGNAL('toggled(bool)'), self.toggle_import)
        self.connect(self.importTalksWidget.importButton, SIGNAL('clicked()'),
                     self.import_talks)
        self.connect(self.importTalksWidget.cancelButton, SIGNAL('clicked()'),
                     self.hide_import_talks_widget)
        self.importTalksWidget.setHidden(True)
        self.connect(self.importTalksWidget.csvFileSelectButton,
                     SIGNAL('clicked()'), self.csv_file_select)
        self.connect(self.importTalksWidget.csvLineEdit,
                     SIGNAL('returnPressed()'),
                     self.importTalksWidget.importButton.click)
        self.connect(self.importTalksWidget.rssLineEdit,
                     SIGNAL('returnPressed()'),
                     self.importTalksWidget.importButton.click)
        self.connect(self.actionExportCsv, SIGNAL('triggered()'),
                     self.export_talks_to_csv)
        self.connect(self.actionRemoveAll, SIGNAL('triggered()'),
                     self.confirm_reset)

        # Command Buttons
        self.connect(self.commandButtons.addButton, SIGNAL('clicked()'),
                     self.click_add_button)
        self.connect(self.commandButtons.removeButton, SIGNAL('clicked()'),
                     self.remove_talk)
        self.connect(self.commandButtons.removeAllButton, SIGNAL('clicked()'),
                     self.confirm_reset)
        self.connect(self.commandButtons.importButton, SIGNAL('clicked()'),
                     self.show_import_talks_widget)
        self.connect(self.commandButtons.exportButton, SIGNAL('clicked()'),
                     self.export_talks_to_csv)
        self.connect(self.commandButtons.searchButton, SIGNAL('clicked()'),
                     self.search_talks)
        self.connect(self.commandButtons.searchLineEdit,
                     SIGNAL('textEdited(QString)'), self.search_talks)
        self.connect(self.commandButtons.searchLineEdit,
                     SIGNAL('returnPressed()'), self.search_talks)

        # Talk Details Buttons
        self.connect(self.talkDetailsWidget.saveButton, SIGNAL('clicked()'),
                     self.update_talk)

        # Talk Details Widget
        self.connect(self.talkDetailsWidget.titleLineEdit,
                     SIGNAL('textEdited(const QString)'), self.enable_save)
        self.connect(self.talkDetailsWidget.presenterLineEdit,
                     SIGNAL('textEdited(const QString)'), self.enable_save)
        self.connect(self.talkDetailsWidget.categoryLineEdit,
                     SIGNAL('textEdited(const QString)'), self.enable_save)
        self.connect(self.talkDetailsWidget.eventLineEdit,
                     SIGNAL('textEdited(const QString)'), self.enable_save)
        self.connect(self.talkDetailsWidget.roomLineEdit,
                     SIGNAL('textEdited(const QString)'), self.enable_save)
        self.connect(self.talkDetailsWidget.descriptionTextEdit,
                     SIGNAL('modificationChanged(bool)'), self.enable_save)
        self.connect(self.talkDetailsWidget.dateEdit,
                     SIGNAL('dateChanged(const QDate)'), self.enable_save)
        self.connect(self.talkDetailsWidget.startTimeEdit,
                     SIGNAL('timeChanged(const QTime)'), self.enable_save)
        self.connect(self.talkDetailsWidget.endTimeEdit,
                     SIGNAL('timeChanged(const QTime)'), self.enable_save)

        # New Talk Widget
        self.newTalkWidget.connect(self.newTalkWidget.addButton,
                                   SIGNAL('clicked()'), self.add_talk)
        self.newTalkWidget.connect(self.newTalkWidget.cancelButton,
                                   SIGNAL('clicked()'),
                                   self.newTalkWidget.reject)

        # Load default language
        actions = self.menuLanguage.actions()
        for action in actions:
            if action.data().toString() == self.config.default_language:
                action.setChecked(True)
                self.translate(action)
                break

        # Load Talk Database
        self.load_presentations_model()

        # Setup Autocompletion
        self.update_autocomplete_fields()

        self.talkDetailsWidget.saveButton.setEnabled(False)

        # Select first item
        #self.tableView.setCurrentIndex(self.proxy.index(0,0))
        #self.talk_selected(self.proxy.index(0,0))

    #
    # Translation
    #
    def retranslate(self):
        self.setWindowTitle(
            self.app.translate("TalkEditorApp", "Freeseer Talk Editor"))

        #
        # Reusable Strings
        #
        self.confirmDBClearTitleString = self.app.translate(
            "TalkEditorApp", "Remove All Talks from Database")
        self.confirmDBClearQuestionString = self.app.translate(
            "TalkEditorApp", "Are you sure you want to clear the DB?")
        self.confirmTalkDetailsClearTitleString = self.app.translate(
            "TalkEditorApp", "Unsaved Data")
        self.confirmTalkDetailsClearQuestionString = self.app.translate(
            "TalkEditorApp", "Unsaved talk details will be lost. Continue?")
        # --- End Reusable Strings

        #
        # Menubar
        #
        self.actionExportCsv.setText(
            self.app.translate("TalkEditorApp", "&Export to CSV"))
        self.actionRemoveAll.setText(
            self.app.translate("TalkEditorApp", "&Remove All Talks"))

        # --- End Menubar

        #
        # TalkDetailsWidget
        #
        self.talkDetailsWidget.titleLabel.setText(
            self.app.translate("TalkEditorApp", "Title"))
        self.talkDetailsWidget.presenterLabel.setText(
            self.app.translate("TalkEditorApp", "Presenter"))
        self.talkDetailsWidget.categoryLabel.setText(
            self.app.translate("TalkEditorApp", "Category"))
        self.talkDetailsWidget.eventLabel.setText(
            self.app.translate("TalkEditorApp", "Event"))
        self.talkDetailsWidget.roomLabel.setText(
            self.app.translate("TalkEditorApp", "Room"))
        self.talkDetailsWidget.dateLabel.setText(
            self.app.translate("TalkEditorApp", "Date"))
        self.talkDetailsWidget.startTimeLabel.setText(
            self.app.translate("TalkEditorApp", "Start Time"))
        self.talkDetailsWidget.endTimeLabel.setText(
            self.app.translate("TalkEditorApp", "End Time"))
        # --- End TalkDetailsWidget

        #
        # Import Talks Widget Translations
        #
        self.importTalksWidget.rssRadioButton.setText(
            self.app.translate("TalkEditorApp", "RSS URL"))
        self.importTalksWidget.csvRadioButton.setText(
            self.app.translate("TalkEditorApp", "CSV File"))
        self.importTalksWidget.importButton.setText(
            self.app.translate("TalkEditorApp", "Import"))
        # --- End Talks Widget Translations

        #
        # Command Button Translations\
        #
        self.commandButtons.importButton.setText(
            self.app.translate("TalkEditorApp", "Import"))
        self.commandButtons.exportButton.setText(
            self.app.translate("TalkEditorApp", "Export"))
        self.commandButtons.addButton.setText(
            self.app.translate("TalkEditorApp", "Add New Talk"))
        self.commandButtons.removeButton.setText(
            self.app.translate("TalkEditorApp", "Remove"))
        self.commandButtons.removeAllButton.setText(
            self.app.translate("TalkEditorApp", "Remove All"))
        # --- End Command Butotn Translations

        #
        # Search Widget Translations
        #
        self.commandButtons.searchButton.setText(
            self.app.translate("TalkEditorApp", "Search"))
        # --- End Command Button Translations

    def load_presentations_model(self):
        # Load Presentation Model
        self.presentationModel = self.db.get_presentations_model()
        self.proxy = QSortFilterProxyModel()
        self.proxy.setSourceModel(self.presentationModel)
        self.tableView.setModel(self.proxy)
        self.proxy.setFilterCaseSensitivity(Qt.CaseInsensitive)

        # Fill table whitespace.
        self.tableView.horizontalHeader().setStretchLastSection(False)
        self.tableView.horizontalHeader().setResizeMode(1, QHeaderView.Stretch)

        # Hide the ID field
        self.tableView.setColumnHidden(0, True)

        # Map data to widgets
        self.mapper = QDataWidgetMapper()
        self.mapper.setModel(self.proxy)
        self.mapper.setSubmitPolicy(QDataWidgetMapper.ManualSubmit)
        self.mapper.addMapping(self.talkDetailsWidget.titleLineEdit, 1)
        self.mapper.addMapping(self.talkDetailsWidget.presenterLineEdit, 2)
        self.mapper.addMapping(self.talkDetailsWidget.categoryLineEdit, 4)
        self.mapper.addMapping(self.talkDetailsWidget.eventLineEdit, 5)
        self.mapper.addMapping(self.talkDetailsWidget.roomLineEdit, 6)
        self.mapper.addMapping(self.talkDetailsWidget.descriptionTextEdit, 3)
        self.mapper.addMapping(self.talkDetailsWidget.dateEdit, 7)
        self.mapper.addMapping(self.talkDetailsWidget.startTimeEdit, 8)
        self.mapper.addMapping(self.talkDetailsWidget.endTimeEdit, 9)

        # Load StringLists
        self.titleList = QStringList(self.db.get_string_list("Title"))
        #self.speakerList = QStringList(self.db.get_speaker_list())
        #self.categoryList = QStringList(self.db.get_category_list())
        #self.eventList = QStringList(self.db.get_event_list())
        #self.roomList = QStringList(self.db.get_room_list())

        #Disble input
        self.talkDetailsWidget.disable_input_fields()

    def search_talks(self):
        # The default value is 0. If the value is -1, the keys will be read from all columns.
        self.proxy.setFilterKeyColumn(-1)
        self.proxy.setFilterFixedString(
            self.commandButtons.searchLineEdit.text())

    def show_save_prompt(self):
        """Prompts the user to save or discard changes, or continue editing."""
        self.savePromptBox.exec_()
        self.savePromptBox.setDefaultButton(self.saveButton)
        return self.savePromptBox.clickedButton()

    def click_talk(self, model):
        """Warns user if there are unsaved changes, and selects talk clicked by the user."""
        log.info("Selecting row %d", model.row())
        modelRow = model.row()
        if self.unsaved_details_exist():
            log.info("Unsaved changes exist in row %d",
                     self.currentTalkIndex.row())
            confirm = self.show_save_prompt()
            if confirm == self.saveButton:
                log.info("Saving changes in row %d...",
                         self.currentTalkIndex.row())
                self.tableView.selectRow(self.currentTalkIndex.row())
                self.update_talk()
                newModel = self.tableView.currentIndex().sibling(modelRow, 0)
                self.select_talk(newModel)
            elif confirm == self.discardButton:
                log.info("Discarding changes in row %d...",
                         self.currentTalkIndex.row())
                self.talk_selected(model)
            else:
                log.info("Continue editing row %d",
                         self.currentTalkIndex.row())
                self.tableView.selectRow(self.currentTalkIndex.row())
        else:
            self.talk_selected(model)

    def click_add_button(self):
        """Warns user if there are unsaved changes, and shows the New Talk window."""
        if self.unsaved_details_exist():
            log.info("Unsaved changes exist in row %d",
                     self.currentTalkIndex.row())
            confirm = self.show_save_prompt()
            if confirm == self.saveButton:
                log.info("Saving changes in row %d...",
                         self.currentTalkIndex.row())
                self.update_talk()
                self.show_new_talk_popup()
            elif confirm == self.discardButton:
                log.info("Discarding changes in row %d...",
                         self.currentTalkIndex.row())
                # Ensure that changes are discarded
                self.talk_selected(self.currentTalkIndex)
                self.show_new_talk_popup()
            else:
                log.info("Continue editing row %d",
                         self.currentTalkIndex.row())
        else:
            self.show_new_talk_popup()

    def talk_selected(self, model):
        self.mapper.setCurrentIndex(model.row())
        self.talkDetailsWidget.enable_input_fields()
        self.talkDetailsWidget.saveButton.setEnabled(False)
        self.currentTalkIndex = QPersistentModelIndex(model)

    def toggle_import(self):
        if self.importTalksWidget.csvRadioButton.isChecked():
            self.importTalksWidget.csvLineEdit.setEnabled(True)
            self.importTalksWidget.csvFileSelectButton.setEnabled(True)
            self.importTalksWidget.rssLineEdit.setEnabled(False)
        else:
            self.importTalksWidget.csvLineEdit.setEnabled(False)
            self.importTalksWidget.csvFileSelectButton.setEnabled(False)
            self.importTalksWidget.rssLineEdit.setEnabled(True)

    def show_import_talks_widget(self):
        self.commandButtons.setHidden(True)
        self.tableView.setHidden(True)
        self.talkDetailsWidget.setHidden(True)
        self.importTalksWidget.setHidden(False)

    def hide_import_talks_widget(self):
        self.commandButtons.setHidden(False)
        self.tableView.setHidden(False)
        self.talkDetailsWidget.setHidden(False)
        self.importTalksWidget.setHidden(True)

    def add_talk(self):
        """Adds a new talk to the database using data from the NewTalkWidget input fields"""
        presentation = self.create_presentation(
            self.newTalkWidget.talkDetailsWidget)

        if presentation:
            self.db.insert_presentation(presentation)
            self.newTalkWidget.accept()  # Close the dialog

    def update_talk(self):
        """Updates the currently selected talk using data from the TalkEditorApp input fields"""
        selected_talk = self.tableView.currentIndex()
        if selected_talk.row(
        ) >= 0:  # The tableView index begins at 0 and is -1 by default
            talk_id = selected_talk.sibling(selected_talk.row(),
                                            0).data().toString()
            presentation = self.create_presentation(self.talkDetailsWidget)

            if presentation:
                self.db.update_presentation(talk_id, presentation)
                self.apply_changes(selected_talk)
                self.talkDetailsWidget.saveButton.setEnabled(False)

    def create_presentation(self, talkDetailsWidget):
        """Creates and returns an instance of Presentation using data from the input fields"""
        date = talkDetailsWidget.dateEdit.date()
        startTime = talkDetailsWidget.startTimeEdit.time()
        endTime = talkDetailsWidget.endTimeEdit.time()

        title = unicode(talkDetailsWidget.titleLineEdit.text()).strip()
        if title:
            return Presentation(
                unicode(talkDetailsWidget.titleLineEdit.text()).strip(),
                unicode(talkDetailsWidget.presenterLineEdit.text()).strip(),
                unicode(talkDetailsWidget.descriptionTextEdit.toPlainText()).
                strip(),
                unicode(talkDetailsWidget.categoryLineEdit.text()).strip(),
                unicode(talkDetailsWidget.eventLineEdit.text()).strip(),
                unicode(talkDetailsWidget.roomLineEdit.text()).strip(),
                unicode(date.toString(Qt.ISODate)),
                unicode(startTime.toString(Qt.ISODate)),
                unicode(endTime.toString(Qt.ISODate)))

    def show_new_talk_popup(self):
        """Displays a modal dialog with a talk details view

        When Add is selected, a new talk is added to the database using the input field data.
        When Cancel is selected, no talk is added.
        """
        log.info('Opening Add Talk window...')
        self.clear_new_talk_fields()
        self.remove_new_talk_placeholder_text()
        self.newTalkWidget.talkDetailsWidget.titleLineEdit.setFocus()
        if self.newTalkWidget.exec_() == 1:
            self.apply_changes()
            self.talkDetailsWidget.disable_input_fields()
        else:
            log.info('No talk added...')

    def apply_changes(self, updated_talk=None):
        """Repopulates the model to display the effective changes

        Updates the autocomplete fields.
        Displays the updated model in the table view, and selects the newly updated/added talk.
        """
        self.presentationModel.select()
        self.select_talk(updated_talk)
        self.update_autocomplete_fields()

    def select_talk(self, talk=None):
        """Selects the given talk in the table view

        If no talk is given, the last row in the table view is selected.
        """
        if talk:
            row = talk.row()
            column = talk.column()
        else:
            row = self.presentationModel.rowCount() - 1  # Select last row
            column = 0

        self.tableView.selectRow(row)
        self.tableView.setCurrentIndex(self.proxy.index(row, column))
        self.talk_selected(self.proxy.index(row, column))

    def remove_talk(self):
        try:
            rows_selected = self.tableView.selectionModel().selectedRows()
        except:
            return

        # Reversed because rows in list change position once row is removed
        for row in reversed(rows_selected):
            self.presentationModel.removeRow(row.row())
        self.talkDetailsWidget.clear_input_fields()
        self.talkDetailsWidget.disable_input_fields()

    def load_talk(self):
        try:
            self.tableView.currentIndex().row()
        except:
            return

        self.mapper.addMapping(self.talkDetailsWidget.roomLineEdit, 6)
        self.presentationModel.select()

    def reset(self):
        self.db.clear_database()
        self.presentationModel.select()
        self.talkDetailsWidget.clear_input_fields()
        self.talkDetailsWidget.disable_input_fields()

    def confirm_reset(self):
        """Presents a confirmation dialog to ask the user if they are sure they wish to remove the talk database.
        If Yes call the reset() function"""
        confirm = QMessageBox.question(self, self.confirmDBClearTitleString,
                                       self.confirmDBClearQuestionString,
                                       QMessageBox.Yes | QMessageBox.No,
                                       QMessageBox.No)

        if confirm == QMessageBox.Yes:
            self.reset()

    def add_talks_from_rss(self):
        rss_url = unicode(self.importTalksWidget.rssLineEdit.text())
        if rss_url:
            self.db.add_talks_from_rss(rss_url)
            self.presentationModel.select()
            self.hide_import_talks_widget()
        else:
            error = QMessageBox()
            error.setText("Please enter a RSS URL")
            error.exec_()

    def closeEvent(self, event):
        if self.unsaved_details_exist():
            log.info("Unsaved changes exist in row %d",
                     self.currentTalkIndex.row())
            confirm = self.show_save_prompt()
            if confirm == self.saveButton:
                log.info("Saving changes in row %d...",
                         self.currentTalkIndex.row())
                self.update_talk()
                log.info('Exiting talk database editor...')
                self.geometry = self.saveGeometry()
                event.accept()
            elif confirm == self.discardButton:
                log.info("Discarding changes in row %d...",
                         self.currentTalkIndex.row())
                # Ensure that changes are discarded
                self.talk_selected(self.currentTalkIndex)
                log.info('Exiting talk database editor...')
                self.geometry = self.saveGeometry()
                event.accept()
            else:
                log.info("Continue editing row %d",
                         self.currentTalkIndex.row())
                event.ignore()
        else:
            log.info('Exiting talk database editor...')
            self.geometry = self.saveGeometry()
            event.accept()

    def csv_file_select(self):
        fname = QFileDialog.getOpenFileName(self, 'Select file', "", "*.csv")
        if fname:
            self.importTalksWidget.csvLineEdit.setText(fname)

    def add_talks_from_csv(self):
        fname = self.importTalksWidget.csvLineEdit.text()

        if fname:
            self.db.add_talks_from_csv(fname)
            self.presentationModel.select()
            self.hide_import_talks_widget()
        else:
            error = QMessageBox()
            error.setText("Please select a file")
            error.exec_()

    def import_talks(self):
        if self.importTalksWidget.csvRadioButton.isChecked():
            self.add_talks_from_csv()
        else:
            self.add_talks_from_rss()

        self.update_autocomplete_fields()

    def export_talks_to_csv(self):
        fname = QFileDialog.getSaveFileName(self, 'Select file', "", "*.csv")
        if fname:
            self.db.export_talks_to_csv(fname)

    def update_autocomplete_fields(self):
        self.titleList = QStringList(self.db.get_string_list("Title"))
        self.speakerList = QStringList(self.db.get_string_list("Speaker"))
        self.categoryList = QStringList(self.db.get_string_list("Category"))
        self.eventList = QStringList(self.db.get_string_list("Event"))
        self.roomList = QStringList(self.db.get_string_list("Room"))

        self.titleCompleter = QCompleter(self.titleList)
        self.titleCompleter.setCaseSensitivity(Qt.CaseInsensitive)
        self.speakerCompleter = QCompleter(self.speakerList)
        self.speakerCompleter.setCaseSensitivity(Qt.CaseInsensitive)
        self.categoryCompleter = QCompleter(self.categoryList)
        self.categoryCompleter.setCaseSensitivity(Qt.CaseInsensitive)
        self.eventCompleter = QCompleter(self.eventList)
        self.eventCompleter.setCaseSensitivity(Qt.CaseInsensitive)
        self.roomCompleter = QCompleter(self.roomList)
        self.roomCompleter.setCaseSensitivity(Qt.CaseInsensitive)

        self.talkDetailsWidget.titleLineEdit.setCompleter(self.titleCompleter)
        self.talkDetailsWidget.presenterLineEdit.setCompleter(
            self.speakerCompleter)
        self.talkDetailsWidget.categoryLineEdit.setCompleter(
            self.categoryCompleter)
        self.talkDetailsWidget.eventLineEdit.setCompleter(self.eventCompleter)
        self.talkDetailsWidget.roomLineEdit.setCompleter(self.roomCompleter)

    def are_fields_enabled(self):
        return (self.talkDetailsWidget.titleLineEdit.isEnabled()
                and self.talkDetailsWidget.presenterLineEdit.isEnabled()
                and self.talkDetailsWidget.categoryLineEdit.isEnabled()
                and self.talkDetailsWidget.eventLineEdit.isEnabled()
                and self.talkDetailsWidget.roomLineEdit.isEnabled()
                and self.talkDetailsWidget.dateEdit.isEnabled()
                and self.talkDetailsWidget.startTimeEdit.isEnabled()
                and self.talkDetailsWidget.endTimeEdit.isEnabled())

    def unsaved_details_exist(self):
        """Checks if changes have been made to new/existing talk details

        Looks for text in the input fields and check the enabled state of the Save Talk button
        If the Save Talk button is enabled, the input fields contain modified values
        """
        return (self.talkDetailsWidget.saveButton.isEnabled() and
                (self.talkDetailsWidget.titleLineEdit.text()
                 or self.talkDetailsWidget.presenterLineEdit.text()
                 or self.talkDetailsWidget.categoryLineEdit.text()
                 or self.talkDetailsWidget.descriptionTextEdit.toPlainText()))

    def enable_save(self):
        self.talkDetailsWidget.saveButton.setEnabled(True)

    def clear_new_talk_fields(self):
        """Removes existing data from all NewTalkWidget fields except event, room, date and time"""
        self.newTalkWidget.talkDetailsWidget.titleLineEdit.clear()
        self.newTalkWidget.talkDetailsWidget.presenterLineEdit.clear()
        self.newTalkWidget.talkDetailsWidget.descriptionTextEdit.clear()
        self.newTalkWidget.talkDetailsWidget.categoryLineEdit.clear()

    def remove_new_talk_placeholder_text(self):
        """Removes placeholder text in NewTalkWidget originally set by TalkDetailsWidget"""
        self.newTalkWidget.talkDetailsWidget.titleLineEdit.setPlaceholderText(
            "")
        self.newTalkWidget.talkDetailsWidget.presenterLineEdit.setPlaceholderText(
            "")
        self.newTalkWidget.talkDetailsWidget.categoryLineEdit.setPlaceholderText(
            "")
        self.newTalkWidget.talkDetailsWidget.eventLineEdit.setPlaceholderText(
            "")
        self.newTalkWidget.talkDetailsWidget.roomLineEdit.setPlaceholderText(
            "")
Esempio n. 5
0
class TalkEditorApp(FreeseerApp):
    '''Freeseer talk database editor main gui class'''
    def __init__(self, config, db):
        FreeseerApp.__init__(self)

        self.config = config
        self.db = db

        icon = QIcon()
        icon.addPixmap(QPixmap(':/freeseer/logo.png'), QIcon.Normal, QIcon.Off)
        self.setWindowIcon(icon)
        self.resize(960, 600)

        #
        # Setup Layout
        #
        self.mainWidget = QWidget()
        self.mainLayout = QVBoxLayout()
        self.mainWidget.setLayout(self.mainLayout)
        self.setCentralWidget(self.mainWidget)
        self.mainLayout.setAlignment(Qt.AlignTop)

        # Add custom widgets
        self.commandButtons = CommandButtons()
        self.tableView = QTableView()
        self.tableView.setSortingEnabled(True)
        self.tableView.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.talkDetailsWidget = TalkDetailsWidget()
        self.importTalksWidget = ImportTalksWidget()
        self.newTalkWidget = NewTalkWidget()
        self.mainLayout.addWidget(self.importTalksWidget)
        #self.mainLayout.addLayout(self.titleLayout)
        self.mainLayout.addWidget(self.commandButtons)
        self.mainLayout.addWidget(self.tableView)
        self.mainLayout.addWidget(self.talkDetailsWidget)
        self.mainLayout.addWidget(self.importTalksWidget)
        # --- End Layout

        # Initialize geometry, to be used for restoring window positioning.
        self.geometry = None

        #
        # Setup Menubar
        #
        self.actionExportCsv = QAction(self)
        self.actionExportCsv.setObjectName('actionExportCsv')
        self.actionRemoveAll = QAction(self)
        self.actionRemoveAll.setObjectName('actionRemoveAll')

        # Actions
        self.menuFile.insertAction(self.actionExit, self.actionExportCsv)
        self.menuFile.insertAction(self.actionExit, self.actionRemoveAll)
        # --- End Menubar

        #
        # TableView Connections
        #
        self.connect(self.tableView, SIGNAL('activated(const QModelIndex)'), self.talk_selected)
        self.connect(self.tableView, SIGNAL('selected(const QModelIndex)'), self.talk_selected)
        self.connect(self.tableView, SIGNAL('clicked(const QModelIndex)'), self.talk_selected)

        # Import Widget
        self.connect(self.importTalksWidget.csvRadioButton, SIGNAL('toggled(bool)'), self.toggle_import)
        self.connect(self.importTalksWidget.importButton, SIGNAL('clicked()'), self.import_talks)
        self.connect(self.importTalksWidget.cancelButton, SIGNAL('clicked()'), self.hide_import_talks_widget)
        self.importTalksWidget.setHidden(True)
        self.connect(self.importTalksWidget.csvFileSelectButton, SIGNAL('clicked()'), self.csv_file_select)
        self.connect(self.importTalksWidget.csvLineEdit, SIGNAL('returnPressed()'),
            self.importTalksWidget.importButton.click)
        self.connect(self.importTalksWidget.rssLineEdit, SIGNAL('returnPressed()'),
            self.importTalksWidget.importButton.click)
        self.connect(self.actionExportCsv, SIGNAL('triggered()'), self.export_talks_to_csv)
        self.connect(self.actionRemoveAll, SIGNAL('triggered()'), self.confirm_reset)

        # Command Buttons
        self.connect(self.commandButtons.addButton, SIGNAL('clicked()'), self.show_new_talk_popup)
        self.connect(self.commandButtons.removeButton, SIGNAL('clicked()'), self.remove_talk)
        self.connect(self.commandButtons.removeAllButton, SIGNAL('clicked()'), self.confirm_reset)
        self.connect(self.commandButtons.importButton, SIGNAL('clicked()'), self.show_import_talks_widget)
        self.connect(self.commandButtons.exportButton, SIGNAL('clicked()'), self.export_talks_to_csv)
        self.connect(self.commandButtons.searchButton, SIGNAL('clicked()'), self.search_talks)
        self.connect(self.commandButtons.searchLineEdit, SIGNAL('textEdited(QString)'), self.search_talks)
        self.connect(self.commandButtons.searchLineEdit, SIGNAL('returnPressed()'), self.search_talks)

        # Talk Details Buttons
        self.connect(self.talkDetailsWidget.saveButton, SIGNAL('clicked()'), self.update_talk)

        # Talk Details Widget
        self.connect(self.talkDetailsWidget.titleLineEdit, SIGNAL('textEdited(const QString)'), self.enable_save)
        self.connect(self.talkDetailsWidget.presenterLineEdit, SIGNAL('textEdited(const QString)'), self.enable_save)
        self.connect(self.talkDetailsWidget.categoryLineEdit, SIGNAL('textEdited(const QString)'), self.enable_save)
        self.connect(self.talkDetailsWidget.eventLineEdit, SIGNAL('textEdited(const QString)'), self.enable_save)
        self.connect(self.talkDetailsWidget.roomLineEdit, SIGNAL('textEdited(const QString)'), self.enable_save)
        self.connect(self.talkDetailsWidget.descriptionTextEdit, SIGNAL('modificationChanged(bool)'), self.enable_save)
        self.connect(self.talkDetailsWidget.dateEdit, SIGNAL('dateChanged(const QDate)'), self.enable_save)
        self.connect(self.talkDetailsWidget.startTimeEdit, SIGNAL('timeChanged(const QTime)'), self.enable_save)
        self.connect(self.talkDetailsWidget.endTimeEdit, SIGNAL('timeChanged(const QTime)'), self.enable_save)

        # New Talk Widget
        self.newTalkWidget.connect(self.newTalkWidget.addButton, SIGNAL('clicked()'), self.add_talk)
        self.newTalkWidget.connect(self.newTalkWidget.cancelButton, SIGNAL('clicked()'), self.newTalkWidget.reject)

        # Load default language
        actions = self.menuLanguage.actions()
        for action in actions:
            if action.data().toString() == self.config.default_language:
                action.setChecked(True)
                self.translate(action)
                break

        # Load Talk Database
        self.load_presentations_model()

        # Setup Autocompletion
        self.update_autocomplete_fields()

        self.talkDetailsWidget.saveButton.setEnabled(False)

        # Select first item
        #self.tableView.setCurrentIndex(self.proxy.index(0,0))
        #self.talk_selected(self.proxy.index(0,0))

    #
    # Translation
    #
    def retranslate(self):
        self.setWindowTitle(self.app.translate("TalkEditorApp", "Freeseer Talk Editor"))

        #
        # Reusable Strings
        #
        self.confirmDBClearTitleString = self.app.translate("TalkEditorApp", "Remove All Talks from Database")
        self.confirmDBClearQuestionString = self.app.translate("TalkEditorApp",
                                                               "Are you sure you want to clear the DB?")
        self.confirmTalkDetailsClearTitleString = self.app.translate("TalkEditorApp", "Unsaved Data")
        self.confirmTalkDetailsClearQuestionString = self.app.translate("TalkEditorApp",
                                                                        "Unsaved talk details will be lost. Continue?")
        # --- End Reusable Strings

        #
        # Menubar
        #
        self.actionExportCsv.setText(self.app.translate("TalkEditorApp", "&Export to CSV"))
        self.actionRemoveAll.setText(self.app.translate("TalkEditorApp", "&Remove All Talks"))

        # --- End Menubar

        #
        # TalkDetailsWidget
        #
        self.talkDetailsWidget.titleLabel.setText(self.app.translate("TalkEditorApp", "Title"))
        self.talkDetailsWidget.presenterLabel.setText(self.app.translate("TalkEditorApp", "Presenter"))
        self.talkDetailsWidget.categoryLabel.setText(self.app.translate("TalkEditorApp", "Category"))
        self.talkDetailsWidget.eventLabel.setText(self.app.translate("TalkEditorApp", "Event"))
        self.talkDetailsWidget.roomLabel.setText(self.app.translate("TalkEditorApp", "Room"))
        self.talkDetailsWidget.dateLabel.setText(self.app.translate("TalkEditorApp", "Date"))
        self.talkDetailsWidget.startTimeLabel.setText(self.app.translate("TalkEditorApp", "Start Time"))
        self.talkDetailsWidget.endTimeLabel.setText(self.app.translate("TalkEditorApp", "End Time"))
        # --- End TalkDetailsWidget

        #
        # Import Talks Widget Translations
        #
        self.importTalksWidget.rssRadioButton.setText(self.app.translate("TalkEditorApp", "RSS URL"))
        self.importTalksWidget.csvRadioButton.setText(self.app.translate("TalkEditorApp", "CSV File"))
        self.importTalksWidget.importButton.setText(self.app.translate("TalkEditorApp", "Import"))
        # --- End Talks Widget Translations

        #
        # Command Button Translations\
        #
        self.commandButtons.importButton.setText(self.app.translate("TalkEditorApp", "Import"))
        self.commandButtons.exportButton.setText(self.app.translate("TalkEditorApp", "Export"))
        self.commandButtons.addButton.setText(self.app.translate("TalkEditorApp", "Add New Talk"))
        self.commandButtons.removeButton.setText(self.app.translate("TalkEditorApp", "Remove"))
        self.commandButtons.removeAllButton.setText(self.app.translate("TalkEditorApp", "Remove All"))
        # --- End Command Butotn Translations

        #
        # Search Widget Translations
        #
        self.commandButtons.searchButton.setText(self.app.translate("TalkEditorApp", "Search"))
        # --- End Command Button Translations

    def load_presentations_model(self):
        # Load Presentation Model
        self.presentationModel = self.db.get_presentations_model()
        self.proxy = QSortFilterProxyModel()
        self.proxy.setSourceModel(self.presentationModel)
        self.tableView.setModel(self.proxy)
        self.proxy.setFilterCaseSensitivity(Qt.CaseInsensitive)

        # Fill table whitespace.
        self.tableView.horizontalHeader().setStretchLastSection(False)
        self.tableView.horizontalHeader().setResizeMode(1, QHeaderView.Stretch)

        # Hide the ID field
        self.tableView.setColumnHidden(0, True)

        # Map data to widgets
        self.mapper = QDataWidgetMapper()
        self.mapper.setModel(self.proxy)
        self.mapper.setSubmitPolicy(QDataWidgetMapper.ManualSubmit)
        self.mapper.addMapping(self.talkDetailsWidget.titleLineEdit, 1)
        self.mapper.addMapping(self.talkDetailsWidget.presenterLineEdit, 2)
        self.mapper.addMapping(self.talkDetailsWidget.categoryLineEdit, 4)
        self.mapper.addMapping(self.talkDetailsWidget.eventLineEdit, 5)
        self.mapper.addMapping(self.talkDetailsWidget.roomLineEdit, 6)
        self.mapper.addMapping(self.talkDetailsWidget.descriptionTextEdit, 3)
        self.mapper.addMapping(self.talkDetailsWidget.dateEdit, 7)
        self.mapper.addMapping(self.talkDetailsWidget.startTimeEdit, 8)
        self.mapper.addMapping(self.talkDetailsWidget.endTimeEdit, 9)

        # Load StringLists
        self.titleList = QStringList(self.db.get_string_list("Title"))
        #self.speakerList = QStringList(self.db.get_speaker_list())
        #self.categoryList = QStringList(self.db.get_category_list())
        #self.eventList = QStringList(self.db.get_event_list())
        #self.roomList = QStringList(self.db.get_room_list())

        #Disble input
        self.talkDetailsWidget.disable_input_fields()

    def search_talks(self):
        # The default value is 0. If the value is -1, the keys will be read from all columns.
        self.proxy.setFilterKeyColumn(-1)
        self.proxy.setFilterFixedString(self.commandButtons.searchLineEdit.text())

    def talk_selected(self, model):
        self.mapper.setCurrentIndex(model.row())
        self.talkDetailsWidget.enable_input_fields()
        self.talkDetailsWidget.saveButton.setEnabled(False)

    def toggle_import(self):
        if self.importTalksWidget.csvRadioButton.isChecked():
            self.importTalksWidget.csvLineEdit.setEnabled(True)
            self.importTalksWidget.csvFileSelectButton.setEnabled(True)
            self.importTalksWidget.rssLineEdit.setEnabled(False)
        else:
            self.importTalksWidget.csvLineEdit.setEnabled(False)
            self.importTalksWidget.csvFileSelectButton.setEnabled(False)
            self.importTalksWidget.rssLineEdit.setEnabled(True)

    def show_import_talks_widget(self):
        self.commandButtons.setHidden(True)
        self.tableView.setHidden(True)
        self.talkDetailsWidget.setHidden(True)
        self.importTalksWidget.setHidden(False)

    def hide_import_talks_widget(self):
        self.commandButtons.setHidden(False)
        self.tableView.setHidden(False)
        self.talkDetailsWidget.setHidden(False)
        self.importTalksWidget.setHidden(True)

    def add_talk(self):
        """Adds a new talk to the database using data from the NewTalkWidget input fields"""
        presentation = self.create_presentation(self.newTalkWidget.talkDetailsWidget)

        if presentation:
            self.db.insert_presentation(presentation)
            self.newTalkWidget.accept()  # Close the dialog

    def update_talk(self):
        """Updates the currently selected talk using data from the TalkEditorApp input fields"""
        selected_talk = self.tableView.currentIndex()
        if selected_talk.row() >= 0:  # The tableView index begins at 0 and is -1 by default
            talk_id = selected_talk.sibling(selected_talk.row(), 0).data().toString()
            presentation = self.create_presentation(self.talkDetailsWidget)

            if presentation:
                self.db.update_presentation(talk_id, presentation)
                self.apply_changes(selected_talk)
                self.talkDetailsWidget.saveButton.setEnabled(False)

    def create_presentation(self, talkDetailsWidget):
        """Creates and returns an instance of Presentation using data from the input fields"""
        date = talkDetailsWidget.dateEdit.date()
        startTime = talkDetailsWidget.startTimeEdit.time()
        endTime = talkDetailsWidget.endTimeEdit.time()

        title = unicode(talkDetailsWidget.titleLineEdit.text()).strip()
        if title:
            return Presentation(
                unicode(talkDetailsWidget.titleLineEdit.text()).strip(),
                unicode(talkDetailsWidget.presenterLineEdit.text()).strip(),
                unicode(talkDetailsWidget.descriptionTextEdit.toPlainText()).strip(),
                unicode(talkDetailsWidget.categoryLineEdit.text()).strip(),
                unicode(talkDetailsWidget.eventLineEdit.text()).strip(),
                unicode(talkDetailsWidget.roomLineEdit.text()).strip(),
                unicode(date.toString(Qt.ISODate)),
                unicode(startTime.toString(Qt.ISODate)),
                unicode(endTime.toString(Qt.ISODate)))

    def show_new_talk_popup(self):
        """Displays a modal dialog with a talk details view

        When Add is selected, a new talk is added to the database using the input field data.
        When Cancel is selected, no talk is added.
        """
        log.info('Opening Add Talk window...')
        self.clear_new_talk_fields()
        self.remove_new_talk_placeholder_text()
        self.newTalkWidget.talkDetailsWidget.titleLineEdit.setFocus()
        if self.newTalkWidget.exec_() == 1:
            self.apply_changes()
            self.talkDetailsWidget.disable_input_fields()
        else:
            log.info('No talk added...')

    def apply_changes(self, updated_talk=None):
        """Repopulates the model to display the effective changes

        Updates the autocomplete fields.
        Displays the updated model in the table view, and selects the newly updated/added talk.
        """
        self.presentationModel.select()
        self.select_talk(updated_talk)
        self.update_autocomplete_fields()

    def select_talk(self, talk=None):
        """Selects the given talk in the table view

        If no talk is given, the last row in the table view is selected.
        """
        if talk:
            row = talk.row()
            column = talk.column()
        else:
            row = self.presentationModel.rowCount() - 1  # Select last row
            column = 0

        self.tableView.selectRow(row)
        self.tableView.setCurrentIndex(self.proxy.index(row, column))
        self.talk_selected(self.proxy.index(row, column))

    def remove_talk(self):
        try:
            rows_selected = self.tableView.selectionModel().selectedRows()
        except:
            return

        # Reversed because rows in list change position once row is removed
        for row in reversed(rows_selected):
            self.presentationModel.removeRow(row.row())

    def load_talk(self):
        try:
            self.tableView.currentIndex().row()
        except:
            return

        self.mapper.addMapping(self.talkDetailsWidget.roomLineEdit, 6)
        self.presentationModel.select()

    def reset(self):
        self.db.clear_database()
        self.presentationModel.select()

    def confirm_reset(self):
        """Presents a confirmation dialog to ask the user if they are sure they wish to remove the talk database.
        If Yes call the reset() function"""
        confirm = QMessageBox.question(self,
                                       self.confirmDBClearTitleString,
                                       self.confirmDBClearQuestionString,
                                       QMessageBox.Yes |
                                       QMessageBox.No,
                                       QMessageBox.No)

        if confirm == QMessageBox.Yes:
            self.reset()

    def add_talks_from_rss(self):
        rss_url = unicode(self.importTalksWidget.rssLineEdit.text())
        if rss_url:
            self.db.add_talks_from_rss(rss_url)
            self.presentationModel.select()
            self.hide_import_talks_widget()
        else:
            error = QMessageBox()
            error.setText("Please enter a RSS URL")
            error.exec_()

    def closeEvent(self, event):
        log.info('Exiting talk database editor...')
        self.geometry = self.saveGeometry()
        event.accept()

    def csv_file_select(self):
        fname = QFileDialog.getOpenFileName(
            self, 'Select file', "", "*.csv")
        if fname:
            self.importTalksWidget.csvLineEdit.setText(fname)

    def add_talks_from_csv(self):
        fname = self.importTalksWidget.csvLineEdit.text()

        if fname:
            self.db.add_talks_from_csv(fname)
            self.presentationModel.select()
            self.hide_import_talks_widget()
        else:
            error = QMessageBox()
            error.setText("Please select a file")
            error.exec_()

    def import_talks(self):
        if self.importTalksWidget.csvRadioButton.isChecked():
            self.add_talks_from_csv()
        else:
            self.add_talks_from_rss()

        self.update_autocomplete_fields()

    def export_talks_to_csv(self):
        fname = QFileDialog.getSaveFileName(self, 'Select file', "", "*.csv")
        if fname:
            self.db.export_talks_to_csv(fname)

    def update_autocomplete_fields(self):
        self.titleList = QStringList(self.db.get_string_list("Title"))
        self.speakerList = QStringList(self.db.get_string_list("Speaker"))
        self.categoryList = QStringList(self.db.get_string_list("Category"))
        self.eventList = QStringList(self.db.get_string_list("Event"))
        self.roomList = QStringList(self.db.get_string_list("Room"))

        self.titleCompleter = QCompleter(self.titleList)
        self.titleCompleter.setCaseSensitivity(Qt.CaseInsensitive)
        self.speakerCompleter = QCompleter(self.speakerList)
        self.speakerCompleter.setCaseSensitivity(Qt.CaseInsensitive)
        self.categoryCompleter = QCompleter(self.categoryList)
        self.categoryCompleter.setCaseSensitivity(Qt.CaseInsensitive)
        self.eventCompleter = QCompleter(self.eventList)
        self.eventCompleter.setCaseSensitivity(Qt.CaseInsensitive)
        self.roomCompleter = QCompleter(self.roomList)
        self.roomCompleter.setCaseSensitivity(Qt.CaseInsensitive)

        self.talkDetailsWidget.titleLineEdit.setCompleter(self.titleCompleter)
        self.talkDetailsWidget.presenterLineEdit.setCompleter(self.speakerCompleter)
        self.talkDetailsWidget.categoryLineEdit.setCompleter(self.categoryCompleter)
        self.talkDetailsWidget.eventLineEdit.setCompleter(self.eventCompleter)
        self.talkDetailsWidget.roomLineEdit.setCompleter(self.roomCompleter)

    def are_fields_enabled(self):
        return (self.talkDetailsWidget.titleLineEdit.isEnabled() and
                self.talkDetailsWidget.presenterLineEdit.isEnabled() and
                self.talkDetailsWidget.categoryLineEdit.isEnabled() and
                self.talkDetailsWidget.eventLineEdit.isEnabled() and
                self.talkDetailsWidget.roomLineEdit.isEnabled() and
                self.talkDetailsWidget.dateEdit.isEnabled() and
                self.talkDetailsWidget.startTimeEdit.isEnabled() and
                self.talkDetailsWidget.endTimeEdit.isEnabled())

    def unsaved_details_exist(self):
        """Checks if changes have been made to new/existing talk details

        Looks for text in the input fields and check the enabled state of the Save Talk button
        If the Save Talk button is enabled, the input fields contain modified values
        """
        return (self.talkDetailsWidget.saveButton.isEnabled() and
                (self.talkDetailsWidget.titleLineEdit.text() or
                self.talkDetailsWidget.presenterLineEdit.text() or
                self.talkDetailsWidget.categoryLineEdit.text() or
                self.talkDetailsWidget.descriptionTextEdit.toPlainText()))

    def enable_save(self):
        self.talkDetailsWidget.saveButton.setEnabled(True)

    def clear_new_talk_fields(self):
        """Removes existing data from all NewTalkWidget fields except event, room, date and time"""
        self.newTalkWidget.talkDetailsWidget.titleLineEdit.clear()
        self.newTalkWidget.talkDetailsWidget.presenterLineEdit.clear()
        self.newTalkWidget.talkDetailsWidget.descriptionTextEdit.clear()
        self.newTalkWidget.talkDetailsWidget.categoryLineEdit.clear()

    def remove_new_talk_placeholder_text(self):
        """Removes placeholder text in NewTalkWidget originally set by TalkDetailsWidget"""
        self.newTalkWidget.talkDetailsWidget.titleLineEdit.setPlaceholderText("")
        self.newTalkWidget.talkDetailsWidget.presenterLineEdit.setPlaceholderText("")
        self.newTalkWidget.talkDetailsWidget.categoryLineEdit.setPlaceholderText("")
        self.newTalkWidget.talkDetailsWidget.eventLineEdit.setPlaceholderText("")
        self.newTalkWidget.talkDetailsWidget.roomLineEdit.setPlaceholderText("")
Esempio n. 6
0
class FrmOperations(QMainWindow, Ui_frmOperations):
    def __init__(self, parent=None):
        super(FrmOperations, self).__init__(parent)
        self.setupUi(self)
        self.__status = False
        self.database = QSqlDatabase.database()

        self.navmodel = QSqlQueryModel()
        self.navproxymodel = QSortFilterProxyModel()
        self.navproxymodel.setFilterKeyColumn(-1)
        self.navproxymodel.setFilterCaseSensitivity(Qt.CaseInsensitive)
        self.navproxymodel.setSourceModel(self.navmodel)

        self.detailsmodel = QSqlQueryModel()
        self.detailsproxymodel = QSortFilterProxyModel()
        self.detailsproxymodel.setSourceModel(self.detailsmodel)

        self.navproxymodel.setDynamicSortFilter(True)
        self.detailsproxymodel.setDynamicSortFilter(True)

        self.mapper = QDataWidgetMapper(self)
        self.mapper.setModel(self.navproxymodel)

        self.user = user.LoggedUser

        self.editModel = None

        self.tableNavigation.setModel(self.navproxymodel)
        self.tableDetails.setModel(self.detailsproxymodel)

        self.tableDetails.setColumnHidden(IDCUENTA, True)
        self.tableDetails.setColumnHidden(IDDOCUMENTOC, True)

        self.actionCancelar.setVisible(False)
        self.actionGuardar.setVisible(False)

        #        self.actionGuardar.activated.connect( self.save )
        self.tableNavigation.selectionModel().selectionChanged[QItemSelection, QItemSelection].connect(
            self.updateDetails
        )

        QTimer.singleShot(0, self.updateModels)

    def updateModels(self):
        try:
            if not self.database.isOpen():
                if not self.database.open():
                    raise UserWarning("No se pudo conectar con la base de datos")
            self.navmodel.setQuery(
                """
            SELECT 
                d.iddocumento, 
                d.ndocimpreso as 'N Doc', 
                d.fechacreacion as 'Fecha', 
                c.descripcion as 'Concepto'
            FROM documentos d
            JOIN conceptos c ON c.idconcepto = d.idconcepto
            WHERE d.idtipodoc = %d
            ORDER BY d.iddocumento DESC
            """
                % constantes.IDAJUSTECONTABLE
            )
            self.detailsmodel.setQuery(
                """
            SELECT 
                cxd.idcuenta,  
                cc.codigo as 'Codigo Cuenta', 
                cc.descripcion as 'Nombre Cuenta',
                CONCAT('C$',FORMAT(cxd.monto,4)) as Monto,
                cxd.iddocumento  
            FROM cuentasxdocumento cxd 
            JOIN cuentascontables cc ON cxd.idcuenta = cc.idcuenta
            JOIN documentos d ON d.iddocumento = cxd.iddocumento 
            WHERE d.idtipodoc = %d
            ORDER BY nlinea 
            """
                % constantes.IDAJUSTECONTABLE
            )

            self.mapper.addMapping(self.dtPicker, FECHACREACION)
            self.mapper.addMapping(self.txtConcept, CONCEPTO)
            self.tableNavigation.selectionModel().setCurrentIndex(
                self.navproxymodel.index(0, 0), QItemSelectionModel.Select
            )

            self.tableNavigation.setColumnHidden(IDDOCUMENTO, True)
            self.tableDetails.setColumnHidden(IDDOCUMENTOC, True)
            self.tableDetails.setColumnHidden(IDCUENTA, True)

            self.tableDetails.setColumnWidth(CODIGO, 240)
            self.tableDetails.setColumnWidth(DESCRIPCION, 250)

            self.tableNavigation.setColumnWidth(FECHACREACION, 200)
            self.tableNavigation.setColumnWidth(CONCEPTO, 250)
        except UserWarning as inst:
            logging.error(inst)
            QMessageBox.critical(self, qApp.organizationName(), unicode(inst))
        except Exception as inst:
            logging.critical(inst)

    def updateDetails(self, selected, _deselected):
        if len(selected.indexes()) > 0:
            self.mapper.setCurrentModelIndex(selected.indexes()[0])
            self.detailsproxymodel.setFilterKeyColumn(IDDOCUMENTOC)
            self.detailsproxymodel.setFilterRegExp(self.navproxymodel.data(selected.indexes()[0]).toString())

    def setStatus(self, status):
        """
        Cambiar el modo del formulario
        
        true = adding
        false = navigating
        
        @param status: El modo del formulario
        @type status:bool
        """

        self.widget.setHidden(status)
        self.txtSearch.setEnabled(not status)
        self.actionNuevo.setVisible(not status)
        self.actionCancelar.setVisible(status)
        self.actionGuardar.setVisible(status)
        self.cbConcepts.setEnabled(status)
        self.tableDetails.setEditTriggers(QTableView.AllEditTriggers if status else QTableView.NoEditTriggers)
        self.tableNavigation.setEnabled(not status)
        self.tableDetails.setEditTriggers(QTableView.AllEditTriggers)
        #        self.stackedWidget.setCurrentIndex( 0 if status else 1 )
        self.stConcepts.setCurrentIndex(1 if status else 0)

    def getStatus(self):
        return self.__status

    status = property(getStatus, setStatus)

    @pyqtSlot()
    def on_actionCancelar_activated(self):
        self.status = False
        self.editModel = None
        self.tableDetails.setModel(self.detailsproxymodel)
        self.tableDetails.setColumnHidden(IDDOCUMENTOC, True)
        self.tableDetails.setColumnHidden(IDCUENTA, True)

    @pyqtSlot()
    def on_actionGuardar_activated(self):
        self.save()

    @pyqtSlot()
    def on_actionNuevo_activated(self):
        try:
            if not self.database.isOpen():
                if not self.database.open():
                    raise UserWarning("No se pudo abrir la base de datos")

            self.editModel = AccountsSelectorModel()
            self.editModel.insertRow(1)

            delegate = AccountsSelectorDelegate(
                QSqlQuery(
                    """
            SELECT 
                c.idcuenta, 
                c.codigo, 
                c.descripcion 
            FROM cuentascontables c 
            JOIN cuentascontables p ON c.padre = p.idcuenta AND p.padre != 1
            """
                )
            )

            self.dtPicker.setDateTime(QDateTime.currentDateTime())
            self.dtPicker.setMaximumDateTime(QDateTime.currentDateTime())

            self.conceptsmodel = QSqlQueryModel()
            q = """
            SELECT
                idconcepto,
                descripcion
            FROM conceptos
            WHERE idtipodoc = %d and idconcepto <>%d
             """ % (
                constantes.IDAJUSTECONTABLE,
                constantes.IDCONCEPTOBALANCEINICIAL,
            )

            self.conceptsmodel.setQuery(q)

            if self.conceptsmodel.rowCount() < 1:
                raise UserWarning(
                    "No existen conceptos para ajustes contables, por favor comuniquese con el administrador del sistema"
                )

            self.cbConcepts.setModel(self.conceptsmodel)
            self.cbConcepts.setModelColumn(1)
            self.tableDetails.setModel(self.editModel)
            self.tableDetails.setColumnHidden(IDCUENTA, True)
            self.tableDetails.setColumnHidden(IDDOCUMENTOC, True)
            self.tableDetails.setItemDelegate(delegate)

            self.status = True

            self.tableDetails.resizeColumnsToContents()
        except UserWarning as inst:
            self.status = False
            QMessageBox.critical(self, qApp.organizationName(), unicode(inst))
            logging.error(unicode(inst))
        except Exception as inst:
            QMessageBox.critical(self, qApp.organizationName(), "Hubo un error al tratar de iniciar un nuevo ajuste")
            logging.critical(unicode(inst))
            self.status = False

    @pyqtSlot("QString")
    def on_txtSearch_textChanged(self, text):

        self.navproxymodel.setFilterRegExp(text)

    def save(self):
        query = QSqlQuery()

        try:
            if not self.editModel.valid:
                raise UserWarning("El documento no es valido, no se puede guardar")

            if not self.database.isOpen():
                if not self.database.open():
                    raise UserWarning("No se pudo conectar con la base de datos")

            if not self.database.transaction():
                raise Exception(u"No se pudo comenzar la transacción")
            #               Cargar el numero del asiento actual
            query.prepare(
                """
            SELECT
                  MAX(CAST(ndocimpreso AS SIGNED))+1
            FROM documentos d
            WHERE idtipodoc=24
            ;
            """
            )

            query.exec_()
            query.first()

            n = query.value(0).toString()
            if n == "0":
                n = "1"

            if not query.prepare(
                """
            INSERT INTO documentos (ndocimpreso, fechacreacion, idconcepto,   idtipodoc)
            VALUES (:ndocimpreso, :fechacreacion, :idconcepto,  %d)
            """
                % constantes.IDAJUSTECONTABLE
            ):
                raise Exception("No se pudo preparar la consulta para guardar el documento")
            query.bindValue(":ndocimpreso", n)
            query.bindValue(":fechacreacion", self.dtPicker.dateTime().toString("yyyyMMddhhmmss"))
            query.bindValue(
                ":idconcepto", self.conceptsmodel.record(self.cbConcepts.currentIndex()).value("idconcepto").toInt()[0]
            )

            if not query.exec_():
                raise Exception("No se pudo ejecutar la consulta para guardar el asiento")

            insertedId = query.lastInsertId().toInt()[0]

            if not query.prepare(
                """
            INSERT INTO personasxdocumento (idpersona, iddocumento, idaccion) 
            VALUES (:usuario, :documento, :idaccion)
            """
            ):
                raise Exception("No se pudo preparar la consulta para insertar el usuario")
            query.bindValue(":usuario", self.user.uid)
            query.bindValue(":documento", insertedId)
            query.bindValue(":idaccion", constantes.ACCCREA)

            if not query.exec_():
                raise Exception(u"No se pudo guardar la relación con el usuario")

            for lineid, line in enumerate(self.editModel.lines):
                if line.valid:
                    line.save(insertedId, lineid + 1)

            if not self.database.commit():
                raise Exception("No se pudo ejecutar la transaccion")
            self.tableDetails.setModel(self.detailsproxymodel)
            self.updateModels()

            self.status = False
        except UserWarning as inst:
            QMessageBox.critical(self, qApp.organizationName(), unicode(inst))
            logging.error(inst)
        except Exception as inst:
            QMessageBox.critical(self, qApp.organizationName(), "Hubo un error al tratar de guardar su ajuste")
            self.database.rollback()
            logging.critical(inst)
            logging.critical(query.lastError().text())
        finally:
            if self.database.isOpen():
                self.database.close()
Esempio n. 7
0
class FileDialog(QDialog, Ui_FileDialog):
    """
  FileDialog class
  """

    #############################################################################
    def __init__(self, parent=None):
        """
    initialize the widget
    """
        QDialog.__init__(self, parent)
        Ui_FileDialog.__init__(self)
        self.setupUi(self)
        #flags = 0
        #flags = Qt.Window | Qt.WindowMinimizeButtonHint;
        #self.setWindowFlags( flags )
        self.hideTckFilter()
        self.__controler = ControlerFileDialog(self, parent.getControler())
        self.connect(self.closeButton, SIGNAL("clicked()"),
                     self.__controler.close)
        self.connect(self.saveButton, SIGNAL("clicked()"),
                     self.__controler.save)
        self.connect(self.advancedSave, SIGNAL("clicked()"),
                     self.__controler.advancedSave)
        self.connect(self.nextButton, SIGNAL("clicked()"),
                     self.__controler.next)

        self.__model = {}
        self.__path = None
        self.__fileExtension = None
        self.__popUp = QMenu(self.tableView)

        self.__jobAction = QAction(self.tr("Job Info"), self.tableView)
        self.connect(self.__jobAction, SIGNAL("triggered()"),
                     self.__controler.jobinfo)
        self.__popUp.addAction(self.__jobAction)

        self.__ancesstorsAction = QAction(self.tr("Get Anccestors"),
                                          self.tableView)
        self.connect(self.__ancesstorsAction, SIGNAL("triggered()"),
                     self.__controler.getancesstots)
        self.__popUp.addAction(self.__ancesstorsAction)

        self.__loginfoAction = QAction(self.tr("Logginig informations"),
                                       self.tableView)
        self.connect(self.__loginfoAction, SIGNAL("triggered()"),
                     self.__controler.loggininginfo)
        self.__popUp.addAction(self.__loginfoAction)

        self.__copyAction = QAction(self.tr("Copy data"), self.tableView)
        self.connect(self.__copyAction, SIGNAL("triggered()"),
                     self.__controler.copy)
        self.__popUp.addAction(self.__copyAction)

        self.tableView.setContextMenuPolicy(Qt.CustomContextMenu)
        self.connect(self.tableView,
                     SIGNAL('customContextMenuRequested(QPoint)'),
                     self.popUpMenu)

        self.__advancedSave = AdvancedSave(self)
        self.__advancedSave.setFocus()

        self.__controler.addChild('AdvancedSave',
                                  self.__advancedSave.getControler())

        self.__historyDialog = HistoryDialog(self)
        self.__controler.addChild('HistoryDialog',
                                  self.__historyDialog.getControler())

        self.connect(self.tckcombo, SIGNAL('currentIndexChanged(QString)'),
                     self.getControler().tckChanged)
        self.__proxy = QSortFilterProxyModel()

        self.connect(self.tckButton, SIGNAL("clicked()"),
                     self.__controler.tckButtonPressed)
        self.connect(self.tckcloseButton, SIGNAL("clicked()"),
                     self.__controler.hideFilterWidget)

        self.filterWidget.setupControler(self)
        self.__controler.addChild('TckFilterWidget',
                                  self.filterWidget.getControler())

    #############################################################################
    def closeEvent(self, event):
        """handles the close action"""
        gLogger.debug(event)
        self.getControler().close()

    #############################################################################
    def getControler(self):
        """returns the controller"""
        return self.__controler

    #############################################################################
    def setModel(self, model):
        """sets the model"""
        self.__model = model

    def updateModel(self, model):
        """updates the model in case of change"""
        self.__model.update(model)

    #############################################################################
    def getModel(self):
        """returns the model"""
        return self.__model

    #############################################################################
    def setPath(self, path):
        """sets the path"""
        self.__path = path

    #############################################################################
    def getPath(self):
        """returns the path"""
        return self.__path

    #############################################################################
    def showNumberOfEvents(self, number):
        """shows the number of events"""
        self.lineEdit_2.setText(str(number))

    #############################################################################
    def showNumberOfFiles(self, number):
        """shows the number of files"""
        self.lineEdit.setText(str(number))

    #############################################################################
    def showEventInputStat(self, number):
        """shows the number of processed input events"""
        self.alleventinputstat.setText(str(number))

    #############################################################################
    def showFilesSize(self, number):
        """shows the size of the files"""
        self.lineEdit_5.setText(str(number) + '  GB')

    #############################################################################
    def showSelectedNumberOfEvents(self, number):
        """shows the selected number of events"""
        self.lineEdit_4.setText(str(number))

    #############################################################################
    def showSelectedEventInputStat(self, number):
        """shows the selected processed input events"""
        self.eventInputstat.setText(str(number))

    #############################################################################
    def showSelectedNumberOfFiles(self, number):
        """shoes the selected number of files"""
        self.lineEdit_3.setText(str(number))

    #############################################################################
    def showSelectedFileSize(self, number):
        """shows the selected file size"""
        self.lineEdit_6.setText(str(number) + '  GB')

    #############################################################################
    def showTotalLuminosity(self, number):
        """shows the total luminosity"""
        self.alltotalluminosity.setText(str(number))

    #############################################################################
    def showSelectedTotalLuminosity(self, number):
        """selected total luminosity"""
        self.totalluminosity.setText(str(number))

    #############################################################################
    def showLuminosity(self, number):
        """luminosity"""
        self.allluminosity.setText(str(number))

    #############################################################################
    def showSelectedLuminosity(self, number):
        """selected luminosity"""
        self.luminosity.setText(str(number))

    #############################################################################
    def showError(self, message):
        """shows the message as an ERROR"""
        QMessageBox.critical(self, "ERROR", message, QMessageBox.Ok)

    #############################################################################
    def showData(self, data):
        """shows the files in the table widget"""
        self.waitCursor()

        tabledata = []

        header = [
            'FileName', 'EventStat', 'FileSize', 'CreationDate', 'JobStart',
            'JobEnd', 'WorkerNode', 'RunNumber', 'FillNumber', 'FullStat',
            'DataqualityFlag', 'EventInputStat', 'TotalLuminosity',
            'Luminosity', 'InstLuminosity', 'TCK'
        ]
        data.update(self.__model)
        keys = data.keys()
        keys.sort()
        for item in keys:
            lfn = data[item]
            i = []
            for info in header:
                value = lfn[info]
                if value == None:
                    value = ''
                i += [value]
            tabledata += [i]

        if len(tabledata) > 0:
            self.filltable(header, tabledata)
        self.arrowCursor()
        return True

    #############################################################################
    def filltable(self, header, tabledata):
        """ fill the table widget"""
        # set the table model

        tm = TableModel(tabledata, header, self)

        self.__proxy.setSourceModel(tm)

        self.tableView.setModel(self.__proxy)
        self.tableView.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.tableView.setSelectionMode(QAbstractItemView.ExtendedSelection)

        self.tableView.setAlternatingRowColors(True)

        sm = self.tableView.selectionModel()
        self.connect(
            sm, SIGNAL("selectionChanged(QItemSelection, QItemSelection)"),
            self.__controler.selection)

        # set the minimum size
        self.setMinimumSize(400, 300)

        # hide grid
        self.tableView.setShowGrid(True)

        # set the font
        #font = QFont("Courier New", 12)
        #self.tableView.setFont(font)

        # hide vertical header
        vh = self.tableView.verticalHeader()
        vh.setVisible(True)

        # set horizontal header properties
        hh = self.tableView.horizontalHeader()
        hh.setStretchLastSection(True)

        # set column width to fit contents
        self.tableView.resizeColumnsToContents()
        self.tableView.setSortingEnabled(True)

        # set row height
        nrows = len(tabledata)
        for row in xrange(nrows):
            self.tableView.setRowHeight(row, 18)

        self.__proxy.sort(0, Qt.AscendingOrder)
        # enable sorting
        # this doesn't work
        #tv.setSortingEnabled(True)

    #############################################################################
    def saveAs(self, filename=''):
        """saves the selected files"""
        saveDialog = QFileDialog(
            self, 'Feicim Save file(s) dialog', QDir.currentPath(),
            'Python option(*.py);;Option file (*.opts);;Text file (*.txt);;CSV (*.csv)'
        )
        saveDialog.setAcceptMode(QFileDialog.AcceptSave)

        saveDialog.selectFile(filename)
        #self.connect(saveDialog, SIGNAL("filterSelected(const QString &)"),self.filter )
        ##saveDialog.setDirectory (QDir.currentPath())
        #filters = ['Option file (*.opts)' ,'Pool xml file (*.xml)','*.txt']
        #filters = ['Option file (*.opts)','*.py','*.txt']
        #saveDialog.setFilter(';;'.join(filters))
        #saveDialog.setFilter('Option file (*.opts);;Text file (*.txt);;Python option')
        #saveDialog.setFileMode(QFileDialog.AnyFile)
        #saveDialog.setViewMode(QFileDialog.Detail)

        ext = ''
        if saveDialog.exec_():
            filename = str(saveDialog.selectedFiles()[0])
            ext = saveDialog.selectedFilter()
            if 'Text file (*.txt)' in ext:
                if not filename.endswith('.txt'):
                    filename += '.txt'
            elif 'Option file (*.opts)' in ext:
                if not filename.endswith('.opts'):
                    filename += '.opts'
            elif 'Python option(*.py)' in ext:
                if not filename.endswith('.py'):
                    filename += '.py'
            elif 'CSV (*.csv)' in ext:
                if not filename.endswith('.csv'):
                    filename += '.csv'
            try:
                open(filename)
            except IOError:
                pass
            else:
                response = QMessageBox.warning(self, "File dialog",
                                               "File exists, overwrite?",
                                               QMessageBox.Ok, QMessageBox.No)
                if response == QMessageBox.No:
                    filename = ''
        if filename == '':
            return '', ''

        return filename, ext

    #############################################################################
    def popUpMenu(self):
        """shows the popup menu"""
        self.__popUp.popup(QCursor.pos())

    #############################################################################
    def showSelection(self, in_dict):
        """ shows the Bookkeeping query, the selected dataset"""

        if in_dict.has_key('ConfigName'):
            self.configname.setText(in_dict["ConfigName"])

        if in_dict.has_key('ConfigVersion'):
            self.configversion.setText(in_dict["ConfigVersion"])

        if in_dict.has_key('ConditionDescription'):
            self.simulation.setText(in_dict["ConditionDescription"])

        if in_dict.has_key('ProcessingPass'):
            self.processing.setText(in_dict["ProcessingPass"])

        if in_dict.has_key('EventTypeId'):
            self.eventtype.setText(in_dict["EventTypeId"])

        if in_dict.has_key('Production'):
            self.production.setText('')

        if in_dict.has_key('FileType'):
            self.filetype.setText(in_dict["FileType"])

        self.progrnameandversion.setText('')

    #############################################################################
    def clearTable(self):
        """clear the elements from the table"""
        #self.tableView().clear()
        self.__model = {}

    #############################################################################
    def fillTckFilter(self, data):
        """fills the tck combo box"""
        tcks = data + ['All']

        self.tckcombo.clear()
        j = 0
        for i in tcks:
            self.tckcombo.addItem(i, QVariant(i))
            if i == 'All':
                self.tckcombo.setCurrentIndex(j)
            j += 1
        #self.tckcombo.view().setSelectionMode(QAbstractItemView.MultiSelection)

    #############################################################################
    def applyFilter(self, data):
        """performs filter over the files"""
        if data == 'All':
            gLogger.debug('applyFilter-ALL')
            self.__proxy.clear()
            self.__proxy.invalidateFilter()
            filterCondition = "^\\S+$"
            gLogger.debug('Filter condition:' + filterCondition)
            self.__proxy.setFilterKeyColumn(15)
            self.__proxy.setFilterRegExp(filterCondition)
            for row in xrange(self.__proxy.rowCount()):
                self.tableView.setRowHeight(row, 18)
        else:
            gLogger.debug('applyFilter-Selected')
            self.__proxy.setFilterKeyColumn(15)
            filterCondition = '%s' % (data)
            gLogger.debug('Filter condition:' + filterCondition)
            self.__proxy.setFilterRegExp(filterCondition)
            for row in xrange(self.__proxy.rowCount()):
                self.tableView.setRowHeight(row, 18)

    def applyListFilter(self, data):
        """specific filter"""
        gLogger.debug('applyListFilter')
        filterCondition = '\\b'
        cond = '('
        for i in data:
            cond += i
            cond += '|'
        cond = cond[:-1]
        filterCondition += cond + ')\\b'
        gLogger.debug('Filter condition:' + filterCondition)
        self.__proxy.setFilterKeyColumn(15)
        self.__proxy.setFilterRegExp(filterCondition)
        for row in xrange(self.__proxy.rowCount()):
            self.tableView.setRowHeight(row, 18)

    #############################################################################
    def showTckFilter(self):
        """shows the tcks"""
        self.tckButton.hide()
        self.tckcloseButton.show()
        self.tckcombo.hide()
        self.filterWidget.show()

    #############################################################################
    def hideTckFilter(self):
        """hides the tcks"""
        self.tckButton.show()
        self.tckcloseButton.hide()
        self.tckcombo.show()
        self.filterWidget.hide()

    #############################################################################
    def getLFNs(self):
        """returns the lfns"""
        lfns = []
        for row in xrange(self.__proxy.rowCount()):
            index = self.__proxy.index(
                row, 0)  # this add the files to my selected list
            lfns += [str(self.__proxy.data(index).toString())]
        return lfns

    #############################################################################
    def waitCursor(self):
        """shows the wait cursor"""
        self.setCursor(Qt.WaitCursor)

    #############################################################################
    def arrowCursor(self):
        """shows the normal cursor"""
        self.setCursor(Qt.ArrowCursor)
Esempio n. 8
0
class TalkEditorApp(FreeseerApp):
    '''Freeseer talk database editor main gui class'''
    def __init__(self, config, db):
        FreeseerApp.__init__(self)

        self.config = config
        self.db = db

        icon = QIcon()
        icon.addPixmap(QPixmap(':/freeseer/logo.png'), QIcon.Normal, QIcon.Off)
        self.setWindowIcon(icon)
        self.resize(960, 600)

        #
        # Setup Layout
        #
        self.mainWidget = QWidget()
        self.mainLayout = QVBoxLayout()
        self.mainWidget.setLayout(self.mainLayout)
        self.setCentralWidget(self.mainWidget)
        self.mainLayout.setAlignment(QtCore.Qt.AlignTop)

        # Add the Title Row (Use BOLD / Big Font)
        #self.titleLayout = QHBoxLayout()
        #self.backButton = QPushButton('Back to Recorder')
        #if backButton:  # Only show the back button if requested by caller
        #    self.titleLayout.addWidget(self.backButton)
        #self.titleLayout.addStretch()

        # Add custom widgets
        self.commandButtons = CommandButtons()
        self.tableView = QTableView()
        self.tableView.setSortingEnabled(True)
        self.tableView.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.talkDetailsWidget = TalkDetailsWidget()
        self.importTalksWidget = ImportTalksWidget()
        self.mainLayout.addWidget(self.importTalksWidget)
        #self.mainLayout.addLayout(self.titleLayout)
        self.mainLayout.addWidget(self.commandButtons)
        self.mainLayout.addWidget(self.tableView)
        self.mainLayout.addWidget(self.talkDetailsWidget)
        self.mainLayout.addWidget(self.importTalksWidget)
        # --- End Layout

        # Initialize geometry, to be used for restoring window positioning.
        self.geometry = None

        #
        # Setup Menubar
        #
        self.actionExportCsv = QAction(self)
        self.actionExportCsv.setObjectName('actionExportCsv')
        self.actionRemoveAll = QAction(self)
        self.actionRemoveAll.setObjectName('actionRemoveAll')

        # Actions
        self.menuFile.insertAction(self.actionExit, self.actionExportCsv)
        self.menuFile.insertAction(self.actionExit, self.actionRemoveAll)
        # --- End Menubar

        #
        # TableView Connections
        #
        self.connect(self.tableView, SIGNAL('activated(const QModelIndex)'), self.talk_selected)
        self.connect(self.tableView, SIGNAL('selected(const QModelIndex)'), self.talk_selected)
        self.connect(self.tableView, SIGNAL('clicked(const QModelIndex)'), self.talk_selected)

        # Import Widget
        self.connect(self.importTalksWidget.csvRadioButton, SIGNAL('toggled(bool)'), self.toggle_import)
        self.connect(self.importTalksWidget.importButton, SIGNAL('clicked()'), self.import_talks)
        self.connect(self.importTalksWidget.cancelButton, SIGNAL('clicked()'), self.hide_import_talks_widget)
        self.importTalksWidget.setHidden(True)
        self.connect(self.importTalksWidget.csvFileSelectButton, QtCore.SIGNAL('clicked()'), self.csv_file_select)
        self.connect(self.importTalksWidget.csvLineEdit, QtCore.SIGNAL('returnPressed()'),
            self.importTalksWidget.importButton.click)
        self.connect(self.importTalksWidget.rssLineEdit, QtCore.SIGNAL('returnPressed()'),
            self.importTalksWidget.importButton.click)
        self.connect(self.actionExportCsv, QtCore.SIGNAL('triggered()'), self.export_talks_to_csv)
        self.connect(self.actionRemoveAll, QtCore.SIGNAL('triggered()'), self.confirm_reset)

        # Command Buttons
        self.connect(self.commandButtons.removeButton, SIGNAL('clicked()'), self.remove_talk)
        self.connect(self.commandButtons.removeAllButton, SIGNAL('clicked()'), self.confirm_reset)
        self.connect(self.commandButtons.importButton, SIGNAL('clicked()'), self.show_import_talks_widget)
        self.connect(self.commandButtons.exportButton, SIGNAL('clicked()'), self.export_talks_to_csv)
        self.connect(self.commandButtons.searchButton, SIGNAL('clicked()'), self.search_talks)
        self.connect(self.commandButtons.searchLineEdit, SIGNAL('textEdited(QString)'), self.search_talks)
        self.connect(self.commandButtons.searchLineEdit, SIGNAL('returnPressed()'), self.search_talks)

        # Talk Details Buttons
        self.connect(self.talkDetailsWidget.addButton, SIGNAL('clicked()'), self.clear_talk_details_widget)
        self.connect(self.talkDetailsWidget.saveButton, SIGNAL('clicked()'), self.add_talk)

        # Load default language
        actions = self.menuLanguage.actions()
        for action in actions:
            if action.data().toString() == self.config.default_language:
                action.setChecked(True)
                self.translate(action)
                break

        # Load Talk Database
        self.load_presentations_model()

        # Setup Autocompletion
        self.update_autocomple_fields()

        # Select first item
        #self.tableView.setCurrentIndex(self.proxy.index(0,0))
        #self.talk_selected(self.proxy.index(0,0))

    #
    # Translation
    #
    def retranslate(self):
        self.setWindowTitle(self.app.translate("TalkEditorApp", "Freeseer Talk Editor"))

        #
        # Reusable Strings
        #
        self.confirmDBClearTitleString = self.app.translate("TalkEditorApp", "Remove All Talks from Database")
        self.confirmDBClearQuestionString = self.app.translate("TalkEditorApp",
            "Are you sure you want to clear the DB?")
        # --- End Reusable Strings

        #
        # Menubar
        #
        self.actionExportCsv.setText(self.app.translate("TalkEditorApp", "&Export to CSV"))
        self.actionRemoveAll.setText(self.app.translate("TalkEditorApp", "&Remove All Talks"))

        # --- End Menubar

        #
        # TalkDetailsWidget
        #
        self.talkDetailsWidget.titleLabel.setText(self.app.translate("TalkEditorApp", "Title"))
        self.talkDetailsWidget.presenterLabel.setText(self.app.translate("TalkEditorApp", "Presenter"))
        self.talkDetailsWidget.categoryLabel.setText(self.app.translate("TalkEditorApp", "Category"))
        self.talkDetailsWidget.eventLabel.setText(self.app.translate("TalkEditorApp", "Event"))
        self.talkDetailsWidget.roomLabel.setText(self.app.translate("TalkEditorApp", "Room"))
        self.talkDetailsWidget.dateLabel.setText(self.app.translate("TalkEditorApp", "Date"))
        self.talkDetailsWidget.timeLabel.setText(self.app.translate("TalkEditorApp", "Time"))
        # --- End TalkDetailsWidget

        #
        # Import Talks Widget Translations
        #
        self.importTalksWidget.rssRadioButton.setText(self.app.translate("TalkEditorApp", "RSS URL"))
        self.importTalksWidget.csvRadioButton.setText(self.app.translate("TalkEditorApp", "CSV File"))
        self.importTalksWidget.importButton.setText(self.app.translate("TalkEditorApp", "Import"))
        # --- End Talks Widget Translations

        #
        # Command Button Translations\
        #
        #self.commandButtons.addButton.setText(self.app.translate("TalkEditorApp", "Add"))
        self.commandButtons.importButton.setText(self.app.translate("TalkEditorApp", "Import"))
        self.commandButtons.exportButton.setText(self.app.translate("TalkEditorApp", "Export"))
        self.commandButtons.removeButton.setText(self.app.translate("TalkEditorApp", "Remove"))
        self.commandButtons.removeAllButton.setText(self.app.translate("TalkEditorApp", "Remove All"))
        # --- End Command Butotn Translations

        #
        # Search Widget Translations
        #
        self.commandButtons.searchButton.setText(self.app.translate("TalkEditorApp", "Search"))
        # --- End Command Button Translations

    def load_presentations_model(self):
        # Load Presentation Model
        self.presentationModel = self.db.get_presentations_model()
        self.proxy = QSortFilterProxyModel()
        self.proxy.setSourceModel(self.presentationModel)
        self.tableView.setModel(self.proxy)
        self.proxy.setFilterCaseSensitivity(QtCore.Qt.CaseInsensitive)

        # Fill table whitespace.
        self.tableView.horizontalHeader().setStretchLastSection(False)
        self.tableView.horizontalHeader().setResizeMode(1, QHeaderView.Stretch)

        # Hide the ID field
        self.tableView.setColumnHidden(0, True)

        # Map data to widgets
        self.mapper = QDataWidgetMapper()
        self.mapper.setModel(self.proxy)
        self.mapper.addMapping(self.talkDetailsWidget.titleLineEdit, 1)
        self.mapper.addMapping(self.talkDetailsWidget.presenterLineEdit, 2)
        self.mapper.addMapping(self.talkDetailsWidget.categoryLineEdit, 4)
        self.mapper.addMapping(self.talkDetailsWidget.eventLineEdit, 5)
        self.mapper.addMapping(self.talkDetailsWidget.roomLineEdit, 6)
        self.mapper.addMapping(self.talkDetailsWidget.descriptionTextEdit, 3)
        self.mapper.addMapping(self.talkDetailsWidget.dateEdit, 7)
        self.mapper.addMapping(self.talkDetailsWidget.timeEdit, 8)

        # Load StringLists
        self.titleList = QStringList(self.db.get_string_list("Title"))
        #self.speakerList = QStringList(self.db.get_speaker_list())
        #self.categoryList = QStringList(self.db.get_category_list())
        #self.eventList = QStringList(self.db.get_event_list())
        #self.roomList = QStringList(self.db.get_room_list())

        #Disble input
        self.talkDetailsWidget.disable_input_fields()

    def search_talks(self):
        # The default value is 0. If the value is -1, the keys will be read from all columns.
        self.proxy.setFilterKeyColumn(-1)
        self.proxy.setFilterFixedString(self.commandButtons.searchLineEdit.text())

    def talk_selected(self, model):
        self.talkDetailsWidget.saveButton.setEnabled(False)
        self.mapper.setCurrentIndex(model.row())
        self.talkDetailsWidget.enable_input_fields()

    def toggle_import(self):
        if self.importTalksWidget.csvRadioButton.isChecked():
            self.importTalksWidget.csvLineEdit.setEnabled(True)
            self.importTalksWidget.csvFileSelectButton.setEnabled(True)
            self.importTalksWidget.rssLineEdit.setEnabled(False)
        else:
            self.importTalksWidget.csvLineEdit.setEnabled(False)
            self.importTalksWidget.csvFileSelectButton.setEnabled(False)
            self.importTalksWidget.rssLineEdit.setEnabled(True)

    def show_import_talks_widget(self):
        self.commandButtons.setHidden(True)
        self.tableView.setHidden(True)
        self.talkDetailsWidget.setHidden(True)
        self.importTalksWidget.setHidden(False)

    def hide_import_talks_widget(self):
        self.commandButtons.setHidden(False)
        self.tableView.setHidden(False)
        self.talkDetailsWidget.setHidden(False)
        self.importTalksWidget.setHidden(True)

    def add_talk(self):
        date = self.talkDetailsWidget.dateEdit.date()
        time = self.talkDetailsWidget.timeEdit.time()
        #datetime = QtCore.QDateTime(date, time)
        presentation = Presentation(
            unicode(self.talkDetailsWidget.titleLineEdit.text()),
            unicode(self.talkDetailsWidget.presenterLineEdit.text()),
            unicode(self.talkDetailsWidget.descriptionTextEdit.toPlainText()),
            unicode(self.talkDetailsWidget.categoryLineEdit.text()),
            unicode(self.talkDetailsWidget.eventLineEdit.text()),
            unicode(self.talkDetailsWidget.roomLineEdit.text()),
            unicode(date.toString(QtCore.Qt.ISODate)),
            unicode(time.toString(QtCore.Qt.ISODate)))

        # Do not add talks if they are empty strings
        if (len(presentation.title) == 0):
            return
        self.db.insert_presentation(presentation)

        # Update Model, Refreshes TableView
        self.presentationModel.select()

        # Select Last Row
        self.tableView.selectRow(self.presentationModel.rowCount() - 1)
        self.tableView.setCurrentIndex(self.proxy.index(self.proxy.rowCount() - 1, 0))
        self.talk_selected(self.proxy.index(self.proxy.rowCount() - 1, 0))

        self.update_autocomple_fields()
        self.talkDetailsWidget.disable_input_fields()

    def clear_talk_details_widget(self):
        self.talkDetailsWidget.saveButton.setEnabled(True)
        self.talkDetailsWidget.enable_input_fields()
        self.talkDetailsWidget.titleLineEdit.clear()
        self.talkDetailsWidget.presenterLineEdit.clear()
        self.talkDetailsWidget.descriptionTextEdit.clear()
        #self.talkDetailsWidget.categoryLineEdit.clear()
        #self.talkDetailsWidget.eventLineEdit.clear()
        #self.talkDetailsWidget.roomLineEdit.clear()
        self.presentationModel.select()

    def remove_talk(self):
        try:
            rows_selected = self.tableView.selectionModel().selectedRows()
        except:
            return

        # Reversed because rows in list change position once row is removed
        for row in reversed(rows_selected):
            self.presentationModel.removeRow(row.row())

    def load_talk(self):
        try:
            self.tableView.currentIndex().row()
        except:
            return

        self.mapper.addMapping(self.talkDetailsWidget.roomLineEdit, 6)
        self.presentationModel.select()

    def reset(self):
        self.db.clear_database()
        self.presentationModel.select()

    def confirm_reset(self):
        """Presents a confirmation dialog to ask the user if they are sure they wish to remove the talk database.
        If Yes call the reset() function"""
        confirm = QMessageBox.question(self,
                                       self.confirmDBClearTitleString,
                                       self.confirmDBClearQuestionString,
                                       QMessageBox.Yes |
                                       QMessageBox.No,
                                       QMessageBox.No)

        if confirm == QMessageBox.Yes:
            self.reset()

    def add_talks_from_rss(self):
        rss_url = unicode(self.importTalksWidget.rssLineEdit.text())
        if rss_url:
            self.db.add_talks_from_rss(rss_url)
            self.presentationModel.select()
            self.hide_import_talks_widget()
        else:
            error = QMessageBox()
            error.setText("Please enter a RSS URL")
            error.exec_()

    def closeEvent(self, event):
        log.info('Exiting talk database editor...')
        self.geometry = self.saveGeometry()
        event.accept()

    def csv_file_select(self):
        fname = QFileDialog.getOpenFileName(
            self, 'Select file', "", "*.csv")
        if fname:
            self.importTalksWidget.csvLineEdit.setText(fname)

    def add_talks_from_csv(self):
        fname = self.importTalksWidget.csvLineEdit.text()

        if fname:
            self.db.add_talks_from_csv(fname)
            self.presentationModel.select()
            self.hide_import_talks_widget()
        else:
            error = QMessageBox()
            error.setText("Please select a file")
            error.exec_()

    def import_talks(self):
        if self.importTalksWidget.csvRadioButton.isChecked():
            self.add_talks_from_csv()
        else:
            self.add_talks_from_rss()

        self.update_autocomple_fields()

    def export_talks_to_csv(self):
        fname = QFileDialog.getSaveFileName(self, 'Select file', "", "*.csv")
        if fname:
            self.db.export_talks_to_csv(fname)

    def update_autocomple_fields(self):
        self.titleList = QStringList(self.db.get_string_list("Title"))
        self.speakerList = QStringList(self.db.get_string_list("Speaker"))
        self.categoryList = QStringList(self.db.get_string_list("Category"))
        self.eventList = QStringList(self.db.get_string_list("Event"))
        self.roomList = QStringList(self.db.get_string_list("Room"))

        self.titleCompleter = QCompleter(self.titleList)
        self.titleCompleter.setCaseSensitivity(Qt.CaseInsensitive)
        self.speakerCompleter = QCompleter(self.speakerList)
        self.speakerCompleter.setCaseSensitivity(Qt.CaseInsensitive)
        self.categoryCompleter = QCompleter(self.categoryList)
        self.categoryCompleter.setCaseSensitivity(Qt.CaseInsensitive)
        self.eventCompleter = QCompleter(self.eventList)
        self.eventCompleter.setCaseSensitivity(Qt.CaseInsensitive)
        self.roomCompleter = QCompleter(self.roomList)
        self.roomCompleter.setCaseSensitivity(Qt.CaseInsensitive)

        self.talkDetailsWidget.titleLineEdit.setCompleter(self.titleCompleter)
        self.talkDetailsWidget.presenterLineEdit.setCompleter(self.speakerCompleter)
        self.talkDetailsWidget.categoryLineEdit.setCompleter(self.categoryCompleter)
        self.talkDetailsWidget.eventLineEdit.setCompleter(self.eventCompleter)
        self.talkDetailsWidget.roomLineEdit.setCompleter(self.roomCompleter)
Esempio n. 9
0
class OWRuleViewer(widget.OWWidget):
    name = "CN2 Rule Viewer"
    description = "Review rules induced from data."
    icon = "icons/CN2RuleViewer.svg"
    priority = 1140

    inputs = [("Data", Table, 'set_data'),
              ("Classifier", _RuleClassifier, 'set_classifier')]

    data_output_identifier = "Filtered data"
    outputs = [(data_output_identifier, Table)]

    compact_view = settings.Setting(False)

    want_basic_layout = True
    want_main_area = True
    want_control_area = False

    def __init__(self):
        self.data = None
        self.classifier = None
        self.selected = None

        self.model = CustomRuleViewerTableModel(parent=self)
        self.model.set_horizontal_header_labels([
            "IF conditions", "", "THEN class", "Distribution",
            "Probabilities [%]", "Quality", "Length"
        ])

        self.proxy_model = QSortFilterProxyModel(parent=self)
        self.proxy_model.setSourceModel(self.model)
        self.proxy_model.setSortRole(self.model.SortRole)

        self.view = gui.TableView(self, wordWrap=False)
        self.view.setModel(self.proxy_model)
        self.view.verticalHeader().setVisible(True)
        self.view.horizontalHeader().setStretchLastSection(False)
        self.view.selectionModel().selectionChanged.connect(self.commit)

        self.dist_item_delegate = DistributionItemDelegate(self)
        self.view.setItemDelegateForColumn(3, self.dist_item_delegate)

        self.mainArea.layout().setContentsMargins(0, 0, 0, 0)
        self.mainArea.layout().addWidget(self.view)
        bottom_box = gui.hBox(widget=self.mainArea,
                              box=None,
                              margin=0,
                              spacing=0)

        original_order_button = QPushButton("Restore original order",
                                            autoDefault=False)
        original_order_button.setFixedWidth(180)
        bottom_box.layout().addWidget(original_order_button)
        original_order_button.clicked.connect(self.restore_original_order)

        gui.separator(bottom_box, width=5, height=0)
        gui.checkBox(widget=bottom_box,
                     master=self,
                     value="compact_view",
                     label="Compact view",
                     callback=self.on_update)

        self.report_button.setFixedWidth(180)
        bottom_box.layout().addWidget(self.report_button)

    def set_data(self, data):
        self.data = data
        self.commit()

    def set_classifier(self, classifier):
        self.classifier = classifier
        self.selected = None
        self.model.clear()

        if classifier is not None and hasattr(classifier, "rule_list"):
            self.model.set_vertical_header_labels(
                list(range(len(classifier.rule_list))))

            self.dist_item_delegate.color_schema = \
                [QColor(*c) for c in classifier.domain.class_var.colors]

            self.model.wrap(self.classifier.domain, self.classifier.rule_list)

        self.on_update()
        self.commit()

    def on_update(self):
        self._save_selected()

        self.model.set_compact_view(self.compact_view)
        if self.compact_view:
            self.view.horizontalHeader().setResizeMode(
                0, QHeaderView.Interactive)  # QHeaderView.Stretch
        else:
            self.view.horizontalHeader().setResizeMode(
                QHeaderView.ResizeToContents)
        self.view.resizeColumnsToContents()
        self.view.resizeRowsToContents()

        self._restore_selected()

    def _save_selected(self, actual=False):
        self.selected = None
        selection_model = self.view.selectionModel()
        if selection_model.hasSelection():
            selection = (selection_model.selection() if not actual else
                         self.proxy_model.mapSelectionToSource(
                             selection_model.selection()))

            self.selected = sorted(
                set(index.row() for index in selection.indexes()))

    def _restore_selected(self):
        if self.selected is not None:
            selection_model = self.view.selectionModel()
            for row in self.selected:
                selection_model.select(
                    self.proxy_model.index(row, 0),
                    selection_model.Select | selection_model.Rows)

    def restore_original_order(self):
        self.proxy_model.sort(-1)

    def copy_to_clipboard(self):
        self._save_selected(actual=True)
        if self.selected is not None:
            output = "\n".join(
                [str(self.classifier.rule_list[i]) for i in self.selected])
            QApplication.clipboard().setText(output)

    def commit(self):
        data_output = None
        self._save_selected(actual=True)

        data = self.data or self.classifier and self.classifier.instances
        if (self.selected is not None and data is not None
                and self.classifier is not None and data.domain.attributes
                == self.classifier.original_domain.attributes):

            status = np.ones(data.X.shape[0], dtype=bool)
            for i in self.selected:
                rule = self.classifier.rule_list[i]
                status &= rule.evaluate_data(data.X)

            data_output = data.from_table_rows(data, status.nonzero()[0])

        self.send(OWRuleViewer.data_output_identifier, data_output)

    def send_report(self):
        if self.classifier is not None:
            self.report_domain("Data domain", self.classifier.original_domain)
            self.report_items("Rule induction algorithm",
                              self.classifier.params)
            self.report_table("Induced rules", self.view)

    def sizeHint(self):
        return QSize(800, 450)
Esempio n. 10
0
class OWRuleViewer(widget.OWWidget):
    name = "CN2 Rule Viewer"
    description = "Review rules induced from data."
    icon = "icons/CN2RuleViewer.svg"
    priority = 1140

    inputs = [("Data", Table, 'set_data'),
              ("Classifier", _RuleClassifier, 'set_classifier')]

    data_output_identifier = "Filtered data"
    outputs = [(data_output_identifier, Table)]

    compact_view = settings.Setting(False)

    want_basic_layout = True
    want_main_area = True
    want_control_area = False

    def __init__(self):
        self.data = None
        self.classifier = None
        self.selected = None

        self.model = CustomRuleViewerTableModel(parent=self)
        self.model.set_horizontal_header_labels(
            ["IF conditions", "", "THEN class", "Distribution",
             "Probabilities [%]", "Quality", "Length"])

        self.proxy_model = QSortFilterProxyModel(parent=self)
        self.proxy_model.setSourceModel(self.model)
        self.proxy_model.setSortRole(self.model.SortRole)

        self.view = gui.TableView(self, wordWrap=False)
        self.view.setModel(self.proxy_model)
        self.view.verticalHeader().setVisible(True)
        self.view.horizontalHeader().setStretchLastSection(False)
        self.view.selectionModel().selectionChanged.connect(self.commit)

        self.dist_item_delegate = DistributionItemDelegate(self)
        self.view.setItemDelegateForColumn(3, self.dist_item_delegate)

        self.mainArea.layout().setContentsMargins(0, 0, 0, 0)
        self.mainArea.layout().addWidget(self.view)
        bottom_box = gui.hBox(widget=self.mainArea, box=None,
                              margin=0, spacing=0)

        original_order_button = QPushButton(
            "Restore original order", autoDefault=False)
        original_order_button.setFixedWidth(180)
        bottom_box.layout().addWidget(original_order_button)
        original_order_button.clicked.connect(self.restore_original_order)

        gui.separator(bottom_box, width=5, height=0)
        gui.checkBox(widget=bottom_box, master=self, value="compact_view",
                     label="Compact view", callback=self.on_update)

        self.report_button.setFixedWidth(180)
        bottom_box.layout().addWidget(self.report_button)

    def set_data(self, data):
        self.data = data
        self.commit()

    def set_classifier(self, classifier):
        self.classifier = classifier
        self.selected = None
        self.model.clear()

        if classifier is not None and hasattr(classifier, "rule_list"):
            self.model.set_vertical_header_labels(
                list(range(len(classifier.rule_list))))

            self.dist_item_delegate.color_schema = \
                [QColor(*c) for c in classifier.domain.class_var.colors]

            self.model.wrap(self.classifier.domain, self.classifier.rule_list)

        self.on_update()
        self.commit()

    def on_update(self):
        self._save_selected()

        self.model.set_compact_view(self.compact_view)
        if self.compact_view:
            self.view.horizontalHeader().setResizeMode(
                0, QHeaderView.Interactive)  # QHeaderView.Stretch
        else:
            self.view.horizontalHeader().setResizeMode(
                QHeaderView.ResizeToContents)
        self.view.resizeColumnsToContents()
        self.view.resizeRowsToContents()

        self._restore_selected()

    def _save_selected(self, actual=False):
        self.selected = None
        selection_model = self.view.selectionModel()
        if selection_model.hasSelection():
            selection = (selection_model.selection() if not actual
                         else self.proxy_model.mapSelectionToSource(
                                selection_model.selection()))

            self.selected = sorted(set(index.row() for index
                                       in selection.indexes()))

    def _restore_selected(self):
        if self.selected is not None:
            selection_model = self.view.selectionModel()
            for row in self.selected:
                selection_model.select(self.proxy_model.index(row, 0),
                                       selection_model.Select |
                                       selection_model.Rows)

    def restore_original_order(self):
        self.proxy_model.sort(-1)

    def copy_to_clipboard(self):
        self._save_selected(actual=True)
        if self.selected is not None:
            output = "\n".join([str(self.classifier.rule_list[i])
                                for i in self.selected])
            QApplication.clipboard().setText(output)

    def commit(self):
        data_output = None
        self._save_selected(actual=True)

        if (self.selected is not None and
                self.data is not None and
                self.classifier is not None and
                self.data.domain.attributes ==
                self.classifier.original_domain.attributes):

            status = np.ones(self.data.X.shape[0], dtype=bool)
            for i in self.selected:
                rule = self.classifier.rule_list[i]
                status &= rule.evaluate_data(self.data.X)

            data_output = self.data.from_table_rows(
                self.data, status.nonzero()[0])

        self.send(OWRuleViewer.data_output_identifier, data_output)

    def send_report(self):
        if self.classifier is not None:
            self.report_domain("Data domain", self.classifier.original_domain)
            self.report_items("Rule induction algorithm", self.classifier.params)
            self.report_table("Induced rules", self.view)

    def sizeHint(self):
        return QSize(800, 450)
Esempio n. 11
0
class FrmArticlesNew( QDialog, Ui_frmArticlesNew ):
    '''
    classdocs
    '''

    def __init__( self, parent = None ):
        '''
        Constructor
        '''
        super( FrmArticlesNew, self ).__init__( parent )
        self.user = user.LoggedUser
        self.setupUi( self )
        self.catmodel = CategoriesModel()

        self.catproxymodel = TreeFilterProxyModel()
        self.catproxymodel.setSourceModel( self.catmodel )
        self.catproxymodel.setFilterKeyColumn( 0 )
        self.catproxymodel.setFilterCaseSensitivity( Qt.CaseInsensitive )



        self.catvalid = False
        self.cat_id = 0
        self.brand_id = 0
        self.isc = Decimal( 0 )
        self.dai = Decimal( 0 )
        self.comission = Decimal( 0 )
        self.profit = Decimal( 0 )


        self.categoriesview.setModel( self.catproxymodel )
        self.categoriesview.setColumnHidden( 1, True )
        self.categoriesview.resizeColumnToContents( 0 )

        self.brandsmodel = QSqlQueryModel()

        self.cargarMarcas()

        self.brandsproxymodel = QSortFilterProxyModel()
        self.brandsproxymodel.setSourceModel( self.brandsmodel )
        self.brandsproxymodel.setFilterKeyColumn( 1 )
        self.brandsproxymodel.setFilterCaseSensitivity( Qt.CaseInsensitive )
        self.brandsview.setModel( self.brandsproxymodel )
        self.brandsview.setModelColumn( 1 )



        self.buttonBox.rejected.connect( self.reject )
        self.categoriesview.selectionModel().selectionChanged[QItemSelection, QItemSelection].connect( self.update_category )
        self.brandsview.selectionModel().selectionChanged[QItemSelection, QItemSelection].connect( self.updateBrand )

    def cargarMarcas( self ):
        if not QSqlDatabase.database().isOpen():
            if not QSqlDatabase.database().open():
                raise Exception( "No se pudo abrir la base de datos" )

        self.brandsmodel.setQuery( """
        SELECT idmarca, nombre 
        FROM marcas
        """ )
        if  QSqlDatabase.database().isOpen():
            QSqlDatabase.database().close()


    @pyqtSlot()
    def on_buttonBox_accepted( self ):
        if self.valid:
            if QMessageBox.question( self,
                                     qApp.organizationName(),
                                     u"¿Esta seguro que desea añadir el producto?",
                                     QMessageBox.Ok |
                                     QMessageBox.Cancel ) == QMessageBox.Ok:
                if not self.save():
                    QMessageBox.critical( self,
                                          qApp.organizationName(),
                                          u"Lo sentimos pero no se ha"\
                                          + " podido guardar el articulo" )
                else:
                    super( FrmArticlesNew, self ).accept()
        else:
            QMessageBox.warning( self,
                                 qApp.organizationName(),
                                 u"Lo sentimos pero los datos no son"\
                                 + " validos, recuerde elegir una subcategoria"\
                                 + " y una marca" )


    def save( self ):
        """
        Guardar el nuevo articulo en la base de datos
        """
        query = QSqlQuery()
        result = False
        try:
            if not QSqlDatabase.database().isOpen():
                if not QSqlDatabase.open():
                    raise UserWarning( u"No se pudo conectar con la"\
                                       + " base de datos" )


            query.prepare( """
                    CALL spAgregarArticulos(
                        :activo,
                        :marca, 
                        :subcategoria, 
                        :dai,
                        :isc, 
                        :comision, 
                        :ganancia 
                        )
                        """ )
            query.bindValue( ":activo", 1 )
            query.bindValue( ":marca", self.brand_id )
            query.bindValue( ":subcategoria", self.cat_id )
            query.bindValue( ":dai", str( self.dai ) )
            query.bindValue( ":isc", str( self.isc ) )
            query.bindValue( ":comision", str( self.comission ) )
            query.bindValue( ":ganancia", str( self.profit ) )

            if not query.exec_():
                raise Exception( "No se pudo ejecutar la consulta" )

            result = True

        except UserWarning as inst:
            logging.error( query.lastError().text() )
            logging.error( unicode( inst ) )
        except Exception as inst:
            logging.critical( query.lastError().text() )
            logging.critical( unicode( inst ) )

        return result

    @pyqtSlot( unicode )
    def on_txtCategorySearch_textChanged( self, text ):
        self.catproxymodel.setFilterFixedString( text )

    @pyqtSlot( unicode )
    def on_txtBrandSearch_textChanged( self, text ):
        self.brandsproxymodel.setFilterFixedString( text )

    @property
    def valid( self ):
        return self.catvalid and self.brand_id != 0

    @pyqtSlot()
    def on_btnAgregarMarca_pressed( self ):
        marca = ["", True]
        marca_descripcion = ""
        while marca_descripcion == "" and marca[1] == True:
            marca = QInputDialog.getText( self, "Agregar Marca",
                                          "Ingrese la Marca" )
            marca_descripcion = marca[0].strip()
            if marca_descripcion != "":
                proxy = self.brandsproxymodel
                proxy.setFilterRegExp( "^" + marca_descripcion + "$" )

                if proxy.rowCount() > 0:
                    QMessageBox.information( None, "Crear Marca",
                                         "La marca %s ya existe" %
                                          marca_descripcion )
                    marca = ["", True]
                    marca_descripcion = ""

        self.brandsproxymodel.setFilterRegExp( "" )

        if marca[1]:
            if QMessageBox.question( self, qApp.organizationName(),
                                      u"¿Está seguro que desea crear la marca %s ?" %
                                      marca_descripcion,
                                      QMessageBox.Yes | QMessageBox.No
                                       ) == QMessageBox.Yes:
                if not QSqlDatabase.database().isOpen():
                    if not QSqlDatabase.database().open():

                        raise Exception( "No se pudo abrir la base de datos" )
                query = QSqlQuery()
                query.prepare( "INSERT INTO marcas(nombre) VALUES (:marca)" )
                query.bindValue( ":marca", marca_descripcion )
                if not query.exec_():
                    logging.error( query.lastError().text() )
                    QMessageBox.warning( None, "Error al crear la marca",
                                          "No se pudo insertar la marca" )
                else:
                    self.cargarMarcas()


    @pyqtSlot( float )
    def on_sbDAI_valueChanged( self, value ):
        try:
            self.dai = Decimal( str( value ) )
        except ValueError:
            self.dai = 0

    @pyqtSlot( float )
    def on_sbISC_valueChanged( self, value ):
        try:
            self.isc = Decimal( str( value ) )
        except ValueError:
            self.isc = 0


    @pyqtSlot( float )
    def on_sbComission_valueChanged( self, value ):
        try:
            self.comission = Decimal( str( value ) )

        except ValueError:
            self.comission = 0

    @pyqtSlot( float )
    def on_sbProfit_valueChanged( self, value ):
        try:
            self.profit = Decimal( str( value ) )
        except ValueError:
            self.profit = 0

    def updateBrand( self, selected, _deselected ):
        if self.brandsproxymodel.rowCount() >= 0:
            self.brand_id = self.brandsproxymodel.index( 
                                   selected.indexes()[0].row(),
                                    0 ).data().toInt()[0]


    def update_category( self, selected, _deselected ):
        try:
            row = selected.indexes()[0].row()
            parent = selected.indexes()[0].parent()
            self.catvalid = parent.data().toString() != ""
            self.cat_id = self.catproxymodel.data( 
                              self.catproxymodel.index( row, 1,
                                         parent ), Qt.DisplayRole )
        except IndexError:
            pass
Esempio n. 12
0
class dlgSelectCuenta( QDialog ):

    def __init__( self, parent = None ):
        super( dlgSelectCuenta, self ).__init__( parent )
        self.padre = parent

        self.ctaBancomodel = QSqlQueryModel()
        self.ctaBancomodel.setQuery( """
        SELECT
            b.descripcion as Banco,
            cb.ctabancaria as 'No. Cuenta',
            tm.simbolo as Moneda,
            c.codigo as 'Codigo Contable',
            c.idcuenta as Id,
            c.descripcion as 'Cuenta Contable',
            IF(
                con.fecha IS NULL,
                LAST_DAY(MIN(d.fechacreacion)),
                (MAX(con.fecha) + INTERVAL 1 MONTH))
                AS conciliar

        FROM cuentasbancarias cb
        JOIN bancos b ON cb.idbanco=b.idbanco
        JOIN cuentascontables c ON c.idcuenta=cb.idcuentacontable
        JOIN tiposmoneda tm ON tm.idtipomoneda=cb.idtipomoneda
        LEFT JOIN conciliaciones con ON con.idcuentabancaria=cb.idcuentacontable
        LEFT JOIN cuentasxdocumento cd ON cd.idcuenta=c.idcuenta
        LEFT JOIN documentos d ON cd.iddocumento = d.iddocumento
        WHERE d.iddocumento IS NOT NULL
        GROUP BY c.idcuenta
         ;
        """ )
#        
#        if self.ctaBancomodel.rowCount() == 0 :
#            QMessageBox.critical(self,"Cuentas Bancarias","No existe ninguna cuenta bancaria")
#            self.destroy()


        self.setWindowTitle( u"Elija fecha y cuenta bancaria para la conciliación" )
        self.filtermodel = QSortFilterProxyModel()
        self.filtermodel.setSourceModel( self.ctaBancomodel )
        self.filtermodel.setFilterCaseSensitivity( Qt.CaseInsensitive )
        self.filtermodel.setFilterKeyColumn( -1 )

        self.tblCuenta = QTableView()
        self.tblCuenta.setSelectionMode( QAbstractItemView.SingleSelection )
        self.tblCuenta.setSelectionBehavior( QAbstractItemView.SelectRows )

        self.tblCuenta.setModel( self.filtermodel )
        buttonbox = QDialogButtonBox( QDialogButtonBox.Ok | QDialogButtonBox.Cancel )

        self.txtSearch = QLineEdit()
        formlayout = QFormLayout()

        formlayout.addRow( "&Buscar", self.txtSearch )



        self.dtPicker = QDateTimeEdit()
        self.dtPicker.setReadOnly( True )
#        self.dtPicker.setCalendarPopup(True)                                       
        self.dtPicker.setAlignment( Qt.AlignHCenter )
        self.dtPicker.setDisplayFormat( "MMMM 'd'el yyyy" )
#        self.dtPicker.setMinimumDate(QDate(2009,1,1))
        fecha = QDate.currentDate()
        self.dtPicker.setDate( QDate( fecha.year(), fecha.month(), fecha.daysInMonth() ) )

        fechalayout = QFormLayout()
        fechalayout.addRow( "&Fecha", self.dtPicker )

        layout = QVBoxLayout()


        layout.addLayout( fechalayout )
        layout.addWidget( self.tblCuenta )
        layout.addLayout( formlayout )
        layout.addWidget( buttonbox )
        self.setLayout( layout )

        self.setMinimumWidth( 400 )

        buttonbox.accepted.connect( self.aceptar )
        buttonbox.rejected.connect( self.reject )
        self.txtSearch.textChanged[unicode].connect( self.updateFilter )
        self.tblCuenta.selectionModel().currentChanged[QModelIndex, QModelIndex].connect( self.on_tblCuenta_currentChanged )

        self.setModal( True )
        self.setWindowFlags( Qt.Dialog | Qt.MSWindowsFixedSizeDialogHint | Qt.WindowTitleHint )
        self.show()
        self.tblCuenta.setFocus()
        self.tblCuenta.selectRow( 0 )
        self.tblCuenta.setColumnHidden( 4, True )
        self.tblCuenta.setColumnHidden( 5, True )
        self.tblCuenta.setColumnHidden( 6, True )
        self.tblCuenta.horizontalHeader().setStretchLastSection( True )
        self.tblCuenta.resizeColumnsToContents()

    @property
    def data( self ):
        data = {}
        fila = self.tblCuenta.selectionModel().currentIndex().row()
        fecha = self.dtPicker.date()

        data['banco'] = self.filtermodel.index( fila, 0 ).data().toString()
        data['id_cuenta_contable'] = self.filtermodel.index( fila, 4 ).data().toInt()[0]
        data['codigo_cuenta_contable'] = self.filtermodel.index( fila, 3 ).data().toString()
        data['cuenta_bancaria'] = self.filtermodel.index( fila, 5 ).data().toString()
        data['fecha'] = QDate( fecha.year(), fecha.month(), fecha.daysInMonth() )
        data['moneda'] = self.filtermodel.index( fila, 2 ).data().toString()


        if not QSqlDatabase.database().isOpen() and not QSqlDatabase.open():
            raise Exception( QSqlDatabase.lastError() )

        query = QSqlQuery()
        if not query.exec_( "CALL spSaldoCuenta( %d, %s )" % ( 
                data['id_cuenta_contable'],
                QDate( data['fecha'].year(), data['fecha'].month(), data['fecha'].daysInMonth() ).toString( "yyyyMMdd" )
            )
        ):
            raise Exception( query.lastError().text() )

        query.first()

        data['saldo_inicial_libro'] = Decimal( query.value( 0 ).toString() )



        return data

    def aceptar( self ):
        fecha = QDate.currentDate()
        fecha = QDate( fecha.year(), fecha.month(), fecha.daysInMonth() )
        if self.dtPicker.date() > fecha:
            QMessageBox.information( None, "Cuentas Bancarias", "La cuenta seleccionada ya fue conciliada" )
        else:
            return self.accept()


    def exec_( self ):
        if self.ctaBancomodel.rowCount() == 0:
            QMessageBox.critical( self.padre, "Cuentas Bancarias",
                "No existe ninguna cuenta bancaria con movimientos en este mes" )
            return self.reject()
        else:
            return QDialog.exec_( self )

    def updateFilter( self, str ):
        self.filtermodel.setFilterWildcard( str )

#    @pyqtSlot( "QModelIndex" )
#    def on_tblCuenta_clicked(self, index):
    def on_tblCuenta_currentChanged( self, _current, _previous ):
        fila = self.tblCuenta.selectionModel().currentIndex().row()
        fecha = self.filtermodel.index( fila, 6 ).data().toDate()
        if fecha.toString() != "":
            self.dtPicker.setDate( fecha )
        else:
            fecha = QDate.currentDate()
Esempio n. 13
0
class FrmCierreContable( Ui_frmCierreContable, QMainWindow ):
    """
    Implementación de la interfaz cierre contable
    """
    def __init__( self, parent,tipocierre ):
        super( FrmCierreContable, self ).__init__( parent )
        self.setupUi( self )
        self.parentWindow = parent

        self.navmodel = QSqlQueryModel( self )
        self.navproxymodel = QSortFilterProxyModel( self )
        self.navproxymodel.setSourceModel( self.navmodel )

        self.navproxymodel.setFilterKeyColumn( -1 )
        self.navproxymodel.setFilterCaseSensitivity ( Qt.CaseInsensitive )
        self.editmodel = None
        self.fecha = None
        self.status = True
        self.tipocierre=tipocierre
        self.validomensual=None
        self.validoanual=None
        
        self.dtPicker.setMaximumDate( QDate.currentDate() )
        self.dtPicker.setDate( QDate.currentDate() )
        
        self.lbltitulo.setText(self.lbltitulo.text()+" "+self.tipocierre)
        if self.tipocierre=="Anual":
            self.dtPicker.setDisplayFormat("yyyy")        
    @pyqtSlot( QDate )
    def on_dtPicker_dateChanged( self, date ):
        """
        Asignar la fecha al objeto __document
        """
        self.fecha = date
        self.updateModels()

    def updateModels( self):
        try:
            if not QSqlDatabase.database().isOpen():
                if not QSqlDatabase.database().open():
                    raise UserWarning( "No se pudo conectar con la base de datos" )
            query = QSqlQuery()
            if self.tipocierre=="Mensual":         
                'Lista de documentos para cierre mensual'
                q = u"""
                SELECT
                    iddocumento,
                    ndocimpreso as 'No. Documento',
                    td.descripcion as TipoDocumento,
                    format(total ,4)as Total,
                    date_format(fechacreacion,'%s') as Fecha,
                    observacion as Observaciones,
                    estados.descripcion as Estado
                FROM documentos d
                JOIN estadosdocumento estados ON estados.idestado=d.idestado
                JOIN tiposdoc td ON d.idtipodoc=td.idtipodoc
                WHERE MONTH(d.fechacreacion)= %s  AND d.idtipodoc!=%d and d.idtipodoc!= %d
                """ % ( "%d/%m/%Y", self.fecha.toString( "MM" ), +constantes.IDAPERTURA , constantes.IDCIERREMENSUAL )
        
                self.navmodel.setQuery( q )  
                   
            else:
                q=u"""
                SELECT 
                    iddocumento,
                    ndocimpreso as 'No. Documento',
                    td.descripcion as TipoDocumento,
                    format(total ,4)as Total,
                    date_format(fechacreacion,'%s') as Fecha,
                    observacion as Observaciones,
                    estados.descripcion as Estado
                FROM documentos d
                JOIN estadosdocumento estados ON estados.idestado=d.idestado
                JOIN tiposdoc td ON d.idtipodoc=td.idtipodoc
                WHERE d.idtipodoc=%d  
                AND YEAR(d.fechacreacion)=%s""" %("%d/%m/%Y",constantes.IDCIERREMENSUAL,self.fecha.toString( "yyyy" ))              
                self.navmodel.setQuery( q )            
            
            'Verifico si hay documentos'
            if self.navmodel.rowCount() == 0:
                self.toolBar.removeAction( self.actionSave )
            else:
                self.toolBar.addActions( [
                self.actionSave] )
                self.actionSave.triggered.connect( self.save )
    
            self.tabledetails.setModel( self.navproxymodel )
            self.tabledetails.setColumnHidden( 0, True )
            self.tabledetails.resizeColumnsToContents()
        
        except UserWarning as inst:
            logging.error( unicode( inst ) )
            QMessageBox.critical( self, qApp.applicationName(), unicode( inst ) )
            self.toolBar.removeAction( self.actionSave )
            
        except Exception as inst:
            logging.critical( unicode( inst ) )
            self.toolBar.removeAction( self.actionSave )
            QMessageBox.critical( self, qApp.organizationName(),
                                   u"Hubo un error al actualizar la tabla" )

    def validarCierreAnual(self):
        try:
            query=QSqlQuery()
            q=u"""
            SELECT d.iddocumento 
            FROM documentos d 
            WHERE d.idtipodoc=%d  
            AND YEAR(d.fechacreacion)=%s""" %(constantes.IDCIERREMENSUAL,self.fecha.toString( "yyyy" ))
            query.prepare(q)
            
            if not query.exec_():
                raise Exception( "No se pudo ejecutar la consulta para determinar si se cerraron todos los meses del año" )
            
            if query.size()<12 and query.size()>0:
                raise UserWarning( "No se han cerrado todos los meses del Ejercicio" )
            return True
            
        except UserWarning as inst:
            logging.error( unicode( inst ) )
            QMessageBox.critical( self, qApp.applicationName(), unicode( inst ) )
            self.toolBar.removeAction( self.actionSave )
            return False
            
        except Exception as inst:
            logging.critical( unicode( inst ) )
            self.toolBar.removeAction( self.actionSave )
            QMessageBox.warning( self,
             qApp.organizationName(),unicode(inst))
            return False   

    def validarCierreMensual(self):
        try:
            query=QSqlQuery()
            q=u"""
                SELECT d.iddocumento 
                FROM documentos d 
                WHERE d.idtipodoc=%d  
                AND YEAR(d.fechacreacion)=%s""" %(constantes.IDCIERREMENSUAL,self.fecha.toString( "yyyy" ))
            query.prepare(q)
            
            if not query.exec_():
                raise UserWarning( "No se pudo ejecutar la consulta para determinar si existe algun cierre en el año" )         
            if query.size()>0:
                mes=self.fecha.addMonths(-1)             
                q=u"""
                    SELECT d.iddocumento 
                    FROM documentos d 
                    WHERE d.idtipodoc=%d 
                    AND MONTH(fechacreacion)=%s 
                    AND YEAR(d.fechacreacion)=%s""" %(constantes.IDCIERREMENSUAL,mes.toString( "MM"),self.fecha.toString( "yyyy" ))
                query.prepare(q)
                
                if not query.exec_():
                    raise UserWarning( "No se pudo ejecutar la consulta para determinar si se cerro el mes anterior" )         
                if query.size()==0:
                    raise UserWarning( "No se ha cerrado el mes anterior" )        
            
                  
            #Verifico si existe un cierre para el mes en proceso
            q = """
            SELECT
                d2.iddocumento
            FROM documentos d
            JOIN docpadrehijos dp ON d.iddocumento=dp.idpadre
            JOIN documentos d2 ON d2.iddocumento=dp.idhijo
            WHERE d2.idtipodoc=%d and month(d2.fechacreacion)=%s
            LIMIT 1
            """ % ( constantes.IDCIERREMENSUAL, self.fecha.toString( "MM" ) )
            
            query.prepare( q )
            
            if not query.exec_():
                raise UserWarning( "No se pudo ejecutar la consulta para "\
                                   + "verificar si existe un cierre contable" )
            
            #El mes actual no se puede cerrar
            
            hoy=QDate.currentDate()
            if self.fecha.month()==hoy.month() and self.fecha.year() == hoy.year():
                raise UserWarning( "No se puede cerrar el mes en proceso" )
    
            return True
        
        except Exception as inst:
            logging.critical( unicode( inst ) )
            self.toolBar.removeAction( self.actionSave )
            QMessageBox.warning( self,
             qApp.organizationName(),unicode(inst))
             
        return False
               
    def save( self ):
        if QMessageBox.question( self, qApp.organizationName(),
                                u"¿Esta seguro que desea hacer este cierre "+self.tipocierre+"?\n"\
                                + u"Esta accion no se puede deshacer",  
                                 QMessageBox.Ok | QMessageBox.No ) == QMessageBox.Ok:
            docpendientes = True
            for i in range( self.navproxymodel.rowCount() ):
                if self.navproxymodel.index( i, ESTADO ).data( Qt.EditRole ).toString() != "CONFIRMADO" and self.navproxymodel.index( i, ESTADO ).data( Qt.EditRole ).toString() != "ANULADO":
                    docpendientes = False
            if self.tipocierre=="Mensual":
                if docpendientes == False or self.validarCierreMensual()==False:
                    QMessageBox.warning( self,
                        qApp.organizationName(),
                         u"No se realizó el cierre contable Mensual ")
                else:
                    self.saveMensual()                                     
            else: 
                if docpendientes==False or self.validarCierreAnual()==False:
                    QMessageBox.warning( self,
                     qApp.organizationName(),
                     u"No se realizó el cierre contable Anual ")
                else:
                    self.saveAnual()
    def saveAnual(self):
        pass
                
    def saveMensual(self):
        query = QSqlQuery()
        try:
            query.prepare( """
            CALL `spCierreMensual`(:IDCIERRE,
            :MES,
            :ESTADO,
            :ANO,
            :INGRESOSXVENTA,
            :OTROSINGRESOS,
            :COSTOSGASTOSOPERACIONES,
            :GASTOSXVENTAS,
            :GASTOS,
            :GASTOSFINANCIEROS,
            :PRODUCTOSFINANCIEROS,
            :OTROSGASTOS,
            :PERDIDASGANANCIAS)
            """ )
            query.bindValue( ":IDCIERRE", constantes.IDCIERREMENSUAL )
            query.bindValue( ":MES", self.fecha.toString( "MM" ) )
            query.bindValue( ":ESTADO", constantes.CONFIRMADO )
            query.bindValue( ":ANO", self.fecha.toString( "yyyy" ) )
            query.bindValue( ":INGRESOSXVENTA",
                             constantes.INGRESOSXVENTA )
            query.bindValue( ":OTROSINGRESOS",
                             constantes.OTROSINGRESOS )
            query.bindValue( ":COSTOSGASTOSOPERACIONES",
                              constantes.COSTOSGASTOSOPERACIONES )
            query.bindValue( ":GASTOSXVENTAS",
                              constantes.GASTOSXVENTAS )
            query.bindValue( ":GASTOS", constantes.GASTOS )
            query.bindValue( ":GASTOSFINANCIEROS",
                             constantes.GASTOSFINANCIEROS )
            query.bindValue( ":PRODUCTOSFINANCIEROS",
                              constantes.PRODUCTOSFINANCIEROS )
            query.bindValue( ":OTROSGASTOS", constantes.OTROSGASTOS )
            query.bindValue( ":PERDIDASGANANCIAS",
                             constantes.PERDIDASGANANCIAS )
            if not query.exec_():
                raise UserWarning( "No se pudo cerrar el mes contable" )

            self.toolBar.removeAction( self.actionSave )
#                self.toolBar.addActions( self.actionPrint )
#                self.actionPrin.triggered.connect( self.printPreview )

        except UserWarning as inst:

            logging.error( inst )
            logging.error( query.lastError().text() )
            QMessageBox.critical( self, qApp.organizationName(),
                                  unicode( inst ) )
Esempio n. 14
0
class FrmBalanceGeneral( QMainWindow, Ui_frmBalanceGeneral ):
    """
    Formulario para crear nuevas conciliaciones bancarias
    """
    def __init__( self, user, parent = None ):
        """
        Constructor
        """
        super( FrmBalanceGeneral, self ).__init__( parent )
        self.setupUi( self )


        self.user = user
        self.pasivofiltermodel = QSortFilterProxyModel()
        self.model = CuentasModel( self.dtPicker.date() )
        self.activofiltermodel = QSortFilterProxyModel()
        self.capitalfiltermodel = QSortFilterProxyModel()

        self.dtPicker.setMaximumDate( QDate.currentDate() )
        self.dtPicker.setDate( QDate.currentDate() )

    def updateModel( self ):
        try:

            if not QSqlDatabase.database().isOpen():
                if not QSqlDatabase.database().open():
                    raise UserWarning( "No se pudo abrir la base de datos" )



            self.activofiltermodel.setSourceModel( self.model )
            self.activofiltermodel.setFilterKeyColumn( ESDEBE )
            self.activofiltermodel.setFilterRegExp( "1" )
            self.activofiltermodel.setFilterCaseSensitivity( 
                                                        Qt.CaseInsensitive )

            self.activoTree.setModel( self.activofiltermodel )
            self.activoTree.setColumnHidden( IDCUENTA, True )
            self.activoTree.setColumnHidden( HIJOS, True )
            self.activoTree.setColumnHidden( PADRE, True )
            self.activoTree.setColumnHidden( ESDEBE, True )
            self.activoTree.setColumnWidth( CODIGO, 80 )
            self.activoTree.setColumnWidth( DESCRIPCION, 200 )

            total = Decimal( 0 )
            for i in range( self.activofiltermodel.rowCount() ):
                total += Decimal( 
                             self.activofiltermodel.index( i,
                                            ACUMULADO ).data( Qt.EditRole
                                                              ).toString() )

            self.txtactivo.setText( moneyfmt( total, 4, 'C$' ) )

    #        self.pasivoModel = CuentasModel()

            self.pasivofiltermodel.setSourceModel( self.model )
            self.pasivofiltermodel.setFilterKeyColumn( ESDEBE )
            self.pasivofiltermodel.setFilterRegExp( "0" )


            self.pasivoTree.setModel( self.pasivofiltermodel )
            self.pasivoTree.setColumnHidden( IDCUENTA, True )
            self.pasivoTree.setColumnHidden( HIJOS, True )
            self.pasivoTree.setColumnHidden( PADRE, True )
            self.pasivoTree.setColumnHidden( ESDEBE, True )
            self.pasivoTree.setColumnWidth( CODIGO, 80 )
            self.pasivoTree.setColumnWidth( DESCRIPCION, 200 )

            total1 = Decimal( 0 )
            for i in range( self.pasivofiltermodel.rowCount() ):
                total1 += Decimal( 
                                  self.pasivofiltermodel.index( i,
                                                ACUMULADO ).data( Qt.EditRole
                                                               ).toString() )
            self.txtpasivo.setText( moneyfmt( total1, 4, 'C$' ) )


            self.capitalfiltermodel.setSourceModel( self.model )
            self.capitalfiltermodel.setFilterKeyColumn( ESDEBE )
            self.capitalfiltermodel.setFilterRegExp( "2" )

            self.capitalTree.setModel( self.capitalfiltermodel )
            self.capitalTree.setColumnHidden( IDCUENTA, True )
            self.capitalTree.setColumnHidden( HIJOS, True )
            self.capitalTree.setColumnHidden( PADRE, True )
            self.capitalTree.setColumnHidden( ESDEBE, True )
            self.capitalTree.setColumnWidth( CODIGO, 80 )
            self.capitalTree.setColumnWidth( DESCRIPCION, 200 )

            total2 = Decimal( 0 )
            for i in range( self.capitalfiltermodel.rowCount() ):
                total2 += Decimal( 
                                  self.capitalfiltermodel.index( i,
                                             ACUMULADO ).data( Qt.EditRole
                                                                ).toString() )

            self.txtcapital.setText( moneyfmt( total2, 4, 'C$' ) )
            self.txtpasivocapital.setText( moneyfmt( total1 + total2,
                                                      4, 'C$' ) )


    #        self.capitalTree.expandAll()
    #        self.activoTree.expandAll()
    #        self.pasivoTree.expandAll()
        except Exception as inst:
            pass
        finally:
            if QSqlDatabase.database().isOpen():
                QSqlDatabase.database().close()

    @pyqtSlot( QDateTime )
    def on_dtPicker_dateTimeChanged( self, _datetime ):
        """
        Asignar la fecha al objeto __document
        """
        self.updateModel()

    @pyqtSlot()
    def on_actionPreview_activated( self ):
        printer = QPrinter()
        printer.setPageSize( QPrinter.Letter )
        web = "balancegeneral.php?date=%d+%d" % ( 
                                                 self.dtPicker.date().month() ,
                                                 self.dtPicker.date().year() )
        report = frmReportes( web , printer, self )
        report.exec_()
Esempio n. 15
0
class TalkEditorApp(FreeseerApp):
    '''Freeseer talk database editor main gui class'''
    def __init__(self, config, db):
        FreeseerApp.__init__(self)

        self.config = config
        self.db = db

        icon = QIcon()
        icon.addPixmap(QPixmap(':/freeseer/logo.png'), QIcon.Normal, QIcon.Off)
        self.setWindowIcon(icon)
        self.resize(960, 600)

        #
        # Setup Layout
        #
        self.mainWidget = QWidget()
        self.mainLayout = QVBoxLayout()
        self.mainWidget.setLayout(self.mainLayout)
        self.setCentralWidget(self.mainWidget)
        self.mainLayout.setAlignment(QtCore.Qt.AlignTop)

        # Add the Title Row (Use BOLD / Big Font)
        #self.titleLayout = QHBoxLayout()
        #self.backButton = QPushButton('Back to Recorder')
        #if backButton:  # Only show the back button if requested by caller
        #    self.titleLayout.addWidget(self.backButton)
        #self.titleLayout.addStretch()

        # Add custom widgets
        self.commandButtons = CommandButtons()
        self.tableView = QTableView()
        self.tableView.setSortingEnabled(True)
        self.tableView.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.talkDetailsWidget = TalkDetailsWidget()
        self.importTalksWidget = ImportTalksWidget()
        self.mainLayout.addWidget(self.importTalksWidget)
        #self.mainLayout.addLayout(self.titleLayout)
        self.mainLayout.addWidget(self.commandButtons)
        self.mainLayout.addWidget(self.tableView)
        self.mainLayout.addWidget(self.talkDetailsWidget)
        self.mainLayout.addWidget(self.importTalksWidget)
        # --- End Layout

        # Initialize geometry, to be used for restoring window positioning.
        self.geometry = None

        #
        # Setup Menubar
        #
        self.actionExportCsv = QAction(self)
        self.actionExportCsv.setObjectName('actionExportCsv')
        self.actionRemoveAll = QAction(self)
        self.actionRemoveAll.setObjectName('actionRemoveAll')

        # Actions
        self.menuFile.insertAction(self.actionExit, self.actionExportCsv)
        self.menuFile.insertAction(self.actionExit, self.actionRemoveAll)
        # --- End Menubar

        #
        # TableView Connections
        #
        self.connect(self.tableView, SIGNAL('activated(const QModelIndex)'), self.talk_selected)
        self.connect(self.tableView, SIGNAL('selected(const QModelIndex)'), self.talk_selected)
        self.connect(self.tableView, SIGNAL('clicked(const QModelIndex)'), self.talk_selected)

        # Import Widget
        self.connect(self.importTalksWidget.csvRadioButton, SIGNAL('toggled(bool)'), self.toggle_import)
        self.connect(self.importTalksWidget.importButton, SIGNAL('clicked()'), self.import_talks)
        self.connect(self.importTalksWidget.cancelButton, SIGNAL('clicked()'), self.hide_import_talks_widget)
        self.importTalksWidget.setHidden(True)
        self.connect(self.importTalksWidget.csvFileSelectButton, QtCore.SIGNAL('clicked()'), self.csv_file_select)
        self.connect(self.importTalksWidget.csvLineEdit, QtCore.SIGNAL('returnPressed()'),
            self.importTalksWidget.importButton.click)
        self.connect(self.importTalksWidget.rssLineEdit, QtCore.SIGNAL('returnPressed()'),
            self.importTalksWidget.importButton.click)
        self.connect(self.actionExportCsv, QtCore.SIGNAL('triggered()'), self.export_talks_to_csv)
        self.connect(self.actionRemoveAll, QtCore.SIGNAL('triggered()'), self.confirm_reset)

        # Command Buttons
        self.connect(self.commandButtons.removeButton, SIGNAL('clicked()'), self.remove_talk)
        self.connect(self.commandButtons.removeAllButton, SIGNAL('clicked()'), self.confirm_reset)
        self.connect(self.commandButtons.importButton, SIGNAL('clicked()'), self.show_import_talks_widget)
        self.connect(self.commandButtons.exportButton, SIGNAL('clicked()'), self.export_talks_to_csv)
        self.connect(self.commandButtons.searchButton, SIGNAL('clicked()'), self.search_talks)
        self.connect(self.commandButtons.searchLineEdit, SIGNAL('textEdited(QString)'), self.search_talks)
        self.connect(self.commandButtons.searchLineEdit, SIGNAL('returnPressed()'), self.search_talks)

        # Talk Details Buttons
        self.connect(self.talkDetailsWidget.addButton, SIGNAL('clicked()'), self.confirm_add)
        self.connect(self.talkDetailsWidget.saveButton, SIGNAL('clicked()'), self.add_talk)

        # Load default language
        actions = self.menuLanguage.actions()
        for action in actions:
            if action.data().toString() == self.config.default_language:
                action.setChecked(True)
                self.translate(action)
                break

        # Load Talk Database
        self.load_presentations_model()

        # Setup Autocompletion
        self.update_autocomple_fields()

        # Select first item
        #self.tableView.setCurrentIndex(self.proxy.index(0,0))
        #self.talk_selected(self.proxy.index(0,0))

    #
    # Translation
    #
    def retranslate(self):
        self.setWindowTitle(self.app.translate("TalkEditorApp", "Freeseer Talk Editor"))

        #
        # Reusable Strings
        #
        self.confirmDBClearTitleString = self.app.translate("TalkEditorApp", "Remove All Talks from Database")
        self.confirmDBClearQuestionString = self.app.translate("TalkEditorApp",
                                                               "Are you sure you want to clear the DB?")
        self.confirmTalkDetailsClearTitleString = self.app.translate("TalkEditorApp", "Unsaved Data")
        self.confirmTalkDetailsClearQuestionString = self.app.translate("TalkEditorApp",
                                                                        "Unsaved talk details will be lost. Continue?")
        # --- End Reusable Strings

        #
        # Menubar
        #
        self.actionExportCsv.setText(self.app.translate("TalkEditorApp", "&Export to CSV"))
        self.actionRemoveAll.setText(self.app.translate("TalkEditorApp", "&Remove All Talks"))

        # --- End Menubar

        #
        # TalkDetailsWidget
        #
        self.talkDetailsWidget.titleLabel.setText(self.app.translate("TalkEditorApp", "Title"))
        self.talkDetailsWidget.presenterLabel.setText(self.app.translate("TalkEditorApp", "Presenter"))
        self.talkDetailsWidget.categoryLabel.setText(self.app.translate("TalkEditorApp", "Category"))
        self.talkDetailsWidget.eventLabel.setText(self.app.translate("TalkEditorApp", "Event"))
        self.talkDetailsWidget.roomLabel.setText(self.app.translate("TalkEditorApp", "Room"))
        self.talkDetailsWidget.dateLabel.setText(self.app.translate("TalkEditorApp", "Date"))
        self.talkDetailsWidget.timeLabel.setText(self.app.translate("TalkEditorApp", "Time"))
        # --- End TalkDetailsWidget

        #
        # Import Talks Widget Translations
        #
        self.importTalksWidget.rssRadioButton.setText(self.app.translate("TalkEditorApp", "RSS URL"))
        self.importTalksWidget.csvRadioButton.setText(self.app.translate("TalkEditorApp", "CSV File"))
        self.importTalksWidget.importButton.setText(self.app.translate("TalkEditorApp", "Import"))
        # --- End Talks Widget Translations

        #
        # Command Button Translations\
        #
        #self.commandButtons.addButton.setText(self.app.translate("TalkEditorApp", "Add"))
        self.commandButtons.importButton.setText(self.app.translate("TalkEditorApp", "Import"))
        self.commandButtons.exportButton.setText(self.app.translate("TalkEditorApp", "Export"))
        self.commandButtons.removeButton.setText(self.app.translate("TalkEditorApp", "Remove"))
        self.commandButtons.removeAllButton.setText(self.app.translate("TalkEditorApp", "Remove All"))
        # --- End Command Butotn Translations

        #
        # Search Widget Translations
        #
        self.commandButtons.searchButton.setText(self.app.translate("TalkEditorApp", "Search"))
        # --- End Command Button Translations

    def load_presentations_model(self):
        # Load Presentation Model
        self.presentationModel = self.db.get_presentations_model()
        self.proxy = QSortFilterProxyModel()
        self.proxy.setSourceModel(self.presentationModel)
        self.tableView.setModel(self.proxy)
        self.proxy.setFilterCaseSensitivity(QtCore.Qt.CaseInsensitive)

        # Fill table whitespace.
        self.tableView.horizontalHeader().setStretchLastSection(False)
        self.tableView.horizontalHeader().setResizeMode(1, QHeaderView.Stretch)

        # Hide the ID field
        self.tableView.setColumnHidden(0, True)

        # Map data to widgets
        self.mapper = QDataWidgetMapper()
        self.mapper.setModel(self.proxy)
        self.mapper.addMapping(self.talkDetailsWidget.titleLineEdit, 1)
        self.mapper.addMapping(self.talkDetailsWidget.presenterLineEdit, 2)
        self.mapper.addMapping(self.talkDetailsWidget.categoryLineEdit, 4)
        self.mapper.addMapping(self.talkDetailsWidget.eventLineEdit, 5)
        self.mapper.addMapping(self.talkDetailsWidget.roomLineEdit, 6)
        self.mapper.addMapping(self.talkDetailsWidget.descriptionTextEdit, 3)
        self.mapper.addMapping(self.talkDetailsWidget.dateEdit, 7)
        self.mapper.addMapping(self.talkDetailsWidget.timeEdit, 8)

        # Load StringLists
        self.titleList = QStringList(self.db.get_string_list("Title"))
        #self.speakerList = QStringList(self.db.get_speaker_list())
        #self.categoryList = QStringList(self.db.get_category_list())
        #self.eventList = QStringList(self.db.get_event_list())
        #self.roomList = QStringList(self.db.get_room_list())

        #Disble input
        self.talkDetailsWidget.disable_input_fields()

    def search_talks(self):
        # The default value is 0. If the value is -1, the keys will be read from all columns.
        self.proxy.setFilterKeyColumn(-1)
        self.proxy.setFilterFixedString(self.commandButtons.searchLineEdit.text())

    def talk_selected(self, model):
        self.talkDetailsWidget.saveButton.setEnabled(False)
        self.mapper.setCurrentIndex(model.row())
        self.talkDetailsWidget.enable_input_fields()

    def toggle_import(self):
        if self.importTalksWidget.csvRadioButton.isChecked():
            self.importTalksWidget.csvLineEdit.setEnabled(True)
            self.importTalksWidget.csvFileSelectButton.setEnabled(True)
            self.importTalksWidget.rssLineEdit.setEnabled(False)
        else:
            self.importTalksWidget.csvLineEdit.setEnabled(False)
            self.importTalksWidget.csvFileSelectButton.setEnabled(False)
            self.importTalksWidget.rssLineEdit.setEnabled(True)

    def show_import_talks_widget(self):
        self.commandButtons.setHidden(True)
        self.tableView.setHidden(True)
        self.talkDetailsWidget.setHidden(True)
        self.importTalksWidget.setHidden(False)

    def hide_import_talks_widget(self):
        self.commandButtons.setHidden(False)
        self.tableView.setHidden(False)
        self.talkDetailsWidget.setHidden(False)
        self.importTalksWidget.setHidden(True)

    def add_talk(self):
        date = self.talkDetailsWidget.dateEdit.date()
        time = self.talkDetailsWidget.timeEdit.time()
        #datetime = QtCore.QDateTime(date, time)
        presentation = Presentation(
            unicode(self.talkDetailsWidget.titleLineEdit.text()).strip(),
            unicode(self.talkDetailsWidget.presenterLineEdit.text()).strip(),
            unicode(self.talkDetailsWidget.descriptionTextEdit.toPlainText()).strip(),
            unicode(self.talkDetailsWidget.categoryLineEdit.text()).strip(),
            unicode(self.talkDetailsWidget.eventLineEdit.text()).strip(),
            unicode(self.talkDetailsWidget.roomLineEdit.text()).strip(),
            unicode(date.toString(QtCore.Qt.ISODate)),
            unicode(time.toString(QtCore.Qt.ISODate)))

        # Do not add talks if they are empty strings
        if (len(presentation.title) == 0):
            return
        self.db.insert_presentation(presentation)

        # Update Model, Refreshes TableView
        self.presentationModel.select()

        # Select Last Row
        self.tableView.selectRow(self.presentationModel.rowCount() - 1)
        self.tableView.setCurrentIndex(self.proxy.index(self.proxy.rowCount() - 1, 0))
        self.talk_selected(self.proxy.index(self.proxy.rowCount() - 1, 0))

        self.update_autocomple_fields()
        self.talkDetailsWidget.disable_input_fields()

    def confirm_add(self):
        """Requests confirmation before clearing fields for a new talk."""
        if self.are_fields_enabled() and self.unsaved_details_exist():
            confirm = QMessageBox.question(self,
                                           self.confirmTalkDetailsClearTitleString,
                                           self.confirmTalkDetailsClearQuestionString,
                                           QMessageBox.Yes,
                                           QMessageBox.No)

            if confirm == QMessageBox.Yes:
                self.clear_talk_details_widget()
        else:
            self.clear_talk_details_widget()

    def clear_talk_details_widget(self):
        self.talkDetailsWidget.saveButton.setEnabled(True)
        self.talkDetailsWidget.enable_input_fields()
        self.talkDetailsWidget.titleLineEdit.clear()
        self.talkDetailsWidget.presenterLineEdit.clear()
        self.talkDetailsWidget.descriptionTextEdit.clear()
        self.talkDetailsWidget.categoryLineEdit.clear()
        #self.talkDetailsWidget.eventLineEdit.clear()
        #self.talkDetailsWidget.roomLineEdit.clear()
        self.presentationModel.select()

    def remove_talk(self):
        try:
            rows_selected = self.tableView.selectionModel().selectedRows()
        except:
            return

        # Reversed because rows in list change position once row is removed
        for row in reversed(rows_selected):
            self.presentationModel.removeRow(row.row())

    def load_talk(self):
        try:
            self.tableView.currentIndex().row()
        except:
            return

        self.mapper.addMapping(self.talkDetailsWidget.roomLineEdit, 6)
        self.presentationModel.select()

    def reset(self):
        self.db.clear_database()
        self.presentationModel.select()

    def confirm_reset(self):
        """Presents a confirmation dialog to ask the user if they are sure they wish to remove the talk database.
        If Yes call the reset() function"""
        confirm = QMessageBox.question(self,
                                       self.confirmDBClearTitleString,
                                       self.confirmDBClearQuestionString,
                                       QMessageBox.Yes |
                                       QMessageBox.No,
                                       QMessageBox.No)

        if confirm == QMessageBox.Yes:
            self.reset()

    def add_talks_from_rss(self):
        rss_url = unicode(self.importTalksWidget.rssLineEdit.text())
        if rss_url:
            self.db.add_talks_from_rss(rss_url)
            self.presentationModel.select()
            self.hide_import_talks_widget()
        else:
            error = QMessageBox()
            error.setText("Please enter a RSS URL")
            error.exec_()

    def closeEvent(self, event):
        log.info('Exiting talk database editor...')
        self.geometry = self.saveGeometry()
        event.accept()

    def csv_file_select(self):
        fname = QFileDialog.getOpenFileName(
            self, 'Select file', "", "*.csv")
        if fname:
            self.importTalksWidget.csvLineEdit.setText(fname)

    def add_talks_from_csv(self):
        fname = self.importTalksWidget.csvLineEdit.text()

        if fname:
            self.db.add_talks_from_csv(fname)
            self.presentationModel.select()
            self.hide_import_talks_widget()
        else:
            error = QMessageBox()
            error.setText("Please select a file")
            error.exec_()

    def import_talks(self):
        if self.importTalksWidget.csvRadioButton.isChecked():
            self.add_talks_from_csv()
        else:
            self.add_talks_from_rss()

        self.update_autocomple_fields()

    def export_talks_to_csv(self):
        fname = QFileDialog.getSaveFileName(self, 'Select file', "", "*.csv")
        if fname:
            self.db.export_talks_to_csv(fname)

    def update_autocomple_fields(self):
        self.titleList = QStringList(self.db.get_string_list("Title"))
        self.speakerList = QStringList(self.db.get_string_list("Speaker"))
        self.categoryList = QStringList(self.db.get_string_list("Category"))
        self.eventList = QStringList(self.db.get_string_list("Event"))
        self.roomList = QStringList(self.db.get_string_list("Room"))

        self.titleCompleter = QCompleter(self.titleList)
        self.titleCompleter.setCaseSensitivity(Qt.CaseInsensitive)
        self.speakerCompleter = QCompleter(self.speakerList)
        self.speakerCompleter.setCaseSensitivity(Qt.CaseInsensitive)
        self.categoryCompleter = QCompleter(self.categoryList)
        self.categoryCompleter.setCaseSensitivity(Qt.CaseInsensitive)
        self.eventCompleter = QCompleter(self.eventList)
        self.eventCompleter.setCaseSensitivity(Qt.CaseInsensitive)
        self.roomCompleter = QCompleter(self.roomList)
        self.roomCompleter.setCaseSensitivity(Qt.CaseInsensitive)

        self.talkDetailsWidget.titleLineEdit.setCompleter(self.titleCompleter)
        self.talkDetailsWidget.presenterLineEdit.setCompleter(self.speakerCompleter)
        self.talkDetailsWidget.categoryLineEdit.setCompleter(self.categoryCompleter)
        self.talkDetailsWidget.eventLineEdit.setCompleter(self.eventCompleter)
        self.talkDetailsWidget.roomLineEdit.setCompleter(self.roomCompleter)

    def are_fields_enabled(self):
        return (self.talkDetailsWidget.titleLineEdit.isEnabled() and
                self.talkDetailsWidget.presenterLineEdit.isEnabled() and
                self.talkDetailsWidget.categoryLineEdit.isEnabled() and
                self.talkDetailsWidget.eventLineEdit.isEnabled() and
                self.talkDetailsWidget.roomLineEdit.isEnabled() and
                self.talkDetailsWidget.dateEdit.isEnabled() and
                self.talkDetailsWidget.timeEdit.isEnabled())

    def unsaved_details_exist(self):
        """Checks if details exist for a new talk

        Looks for text in the input fields and check the enabled state of the Save Talk button
        If the Save Talk button is enabled, the input fields contain values for a new talk
        Otherwise, the input fields contain values for an existing selected talk
        """
        return (self.talkDetailsWidget.saveButton.isEnabled() and
                (self.talkDetailsWidget.titleLineEdit.text() or
                self.talkDetailsWidget.presenterLineEdit.text() or
                self.talkDetailsWidget.categoryLineEdit.text() or
                self.talkDetailsWidget.descriptionTextEdit.toPlainText()))