class UpgradeWidget(QWidget):
    

    def init_datasource(self):
        self.data_source = DataSource()
    
    def init_view(self):
        self.table = QTableView(self)
        self.table.setMinimumSize(600, 600)

        manager = core.packagemanager.get_package_manager()
        package = manager.get_package("edu.cmu.sv.components", "1.0.0")
        modules = package.descriptors
        apis = []
        self.modules_to_upgrade = []
        for module in modules.values():
            api = self.data_source.api_by_id(module.name)
            if ("1.0" != module.version):
                apis.append(api)
                self.modules_to_upgrade.append(module)

        table_model = QStandardItemModel(len(apis), 4)
        row = 0
        for api in apis:
            table_model.setData(table_model.index(row, 0), QVariant(api['id']))
            table_model.setData(table_model.index(row, 1), QVariant(api['category']))
            table_model.setData(table_model.index(row, 2), QVariant(api['version']))
            table_model.setData(table_model.index(row, 3), QVariant(api['description']))
            row += 1

        table_model.setHeaderData(0, Qt.Horizontal, QVariant("Link"))
        table_model.setHeaderData(1, Qt.Horizontal, QVariant("Category"))
        table_model.setHeaderData(2, Qt.Horizontal, QVariant("Version"))
        table_model.setHeaderData(3, Qt.Horizontal, QVariant("Description"))
        self.table.setModel(table_model)


        btn = QPushButton(self)
        btn.clicked.connect(self.upgrade_api)
        btn.setText("Upgrade")
        btn.move(600, 500)

    def upgrade_api(self):
        model = self.table.selectionModel()
        indexes = model.selectedIndexes()
        for index in indexes:
            module = self.modules_to_upgrade[index.row()]
            now = datetime.datetime.now()
            name = "%s %d-%d-%d" % (module.name, now.year, now.month, now.day)
            manager = core.packagemanager.get_package_manager()
            package = manager.get_package("edu.cmu.sv.components", "1.0.0")
            new_module = vistrails_module.new_module(Module, name)
            core.modules.module_registry.set_current_package(package)
            new_descriptor = core.modules.module_registry.get_module_registry().add_module(new_module)
            core.modules.module_registry.get_module_registry().update_module(module, new_descriptor)
#            core.modules.module_registry.get_module_registry().delete_module(module.identifier, module.name)
            self.hide()
            return
Пример #2
0
class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        uic.loadUi("mainwindow.ui", self)

        model = QStandardItemModel(7, 4, self)
        for row in range(7):
            for column in range(4):
                item = QStandardItem(QString("%1").arg(row * 4 + column))
                model.setItem(row, column, item)

        self.tableView = QTableView()
        self.tableView.setModel(model)
        self.setCentralWidget(self.tableView)

        # 获取视图的项目选择模型
        selectionModel = self.tableView.selectionModel()

        # 定义左上角和右下角的索引,然后使用这两个索引创建选择
        topLeft = model.index(1, 1, QModelIndex())
        bottomRight = model.index(5, 2, QModelIndex())
        selection = QItemSelection(topLeft, bottomRight)

        # 使用指定的选择模式来选择项目
        selectionModel.select(selection, QItemSelectionModel.Select)

        self.mainToolBar.addAction(_fromUtf8("当前项目"), self.getCurrentItemData)
        self.mainToolBar.addAction(_fromUtf8("切换选择"), self.toggleSelection)

    # 输出当前项目的内容
    def getCurrentItemData(self, ):

        print  "当前项目的内容:", \
            self.tableView.selectionModel().currentIndex().data().toString()

    # 切换选择的项目
    def toggleSelection(self):
        topLeft = self.tableView.model().index(0, 0, QModelIndex())
        bottomRight = self.tableView.model().index(
            self.tableView.model().rowCount(QModelIndex()) - 1,
            self.tableView.model().columnCount(QModelIndex()) - 1, QModelIndex())
        curSelection = QItemSelection(topLeft, bottomRight)
        self.tableView.selectionModel().select(curSelection, QItemSelectionModel.Toggle)
Пример #3
0
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(None)
        uic.loadUi("mainwindow.ui", self)

        model = QStandardItemModel(7, 4, self)
        for row in range(7):
            for column in range(4):
                item = QStandardItem(QString("%1").arg(row * 4 + column))
                model.setItem(row, column, item)

        tableView = QTableView()
        tableView.setModel(model)
        self.setCentralWidget(tableView)

        #获取视图的项目选择模型
        selectionModel = tableView.selectionModel()
        # 定义左上角和右下角的索引,然后使用这两个索引创建选择
        topLeft = model.index(1, 1, QModelIndex())
        bottomRight = model.index(5, 2, QModelIndex())
        selection = QItemSelection(topLeft, bottomRight)
        # 使用指定的选择模式来选择项目
        selectionModel.select(selection, QItemSelectionModel.Select)
Пример #4
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("")
Пример #5
0
class OWConfusionMatrix(widget.OWWidget):
    name = "Confusion Matrix"
    description = "Shows a confusion matrix."
    icon = "icons/ConfusionMatrix.svg"
    priority = 1001

    inputs = [{"name": "Evaluation Results",
               "type": Orange.evaluation.testing.Results,
               "handler": "set_results"}]
    outputs = [{"name": "Selected Data",
                "type": Orange.data.Table}]

    quantities = ["Number of instances",
                  "Observed and expected instances",
                  "Proportion of predicted",
                  "Proportion of true"]

    selected_learner = settings.Setting([])
    selected_quantity = settings.Setting(0)
    append_predictions = settings.Setting(True)
    append_probabilities = settings.Setting(False)
    autocommit = settings.Setting(True)

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

        self.results = None
        self.learners = []
        self._invalidated = False

        box = gui.widgetBox(self.controlArea, "Learners")

        self.learners_box = gui.listBox(
            box, self, "selected_learner", "learners",
            callback=self._learner_changed
        )
        box = gui.widgetBox(self.controlArea, "Show")

        combo = gui.comboBox(box, self, "selected_quantity",
                             items=self.quantities,
                             callback=self._update)

        box = gui.widgetBox(self.controlArea, "Selection")

        gui.button(box, self, "Correct",
                   callback=self.select_correct, autoDefault=False)
        gui.button(box, self, "Misclassified",
                   callback=self.select_wrong, autoDefault=False)
        gui.button(box, self, "None",
                   callback=self.select_none, autoDefault=False)

        self.outputbox = box = gui.widgetBox(self.controlArea, "Output")
        gui.checkBox(box, self, "append_predictions",
                     "Append class predictions", callback=self._invalidate)
        gui.checkBox(box, self, "append_probabilities",
                     "Append predicted class probabilities",
                     callback=self._invalidate)

        b = gui.button(box, self, "Commit", callback=self.commit, default=True)
        cb = gui.checkBox(box, self, "autocommit", "Commit automatically")
        gui.setStopper(self, b, cb, "_invalidated", callback=self.commit)

        grid = QGridLayout()
        grid.setContentsMargins(0, 0, 0, 0)
        grid.addWidget(QLabel("Predicted"), 0, 1, Qt.AlignCenter)
        grid.addWidget(VerticalLabel("Correct Class"), 1, 0, Qt.AlignCenter)

        self.tablemodel = QStandardItemModel()
        self.tableview = QTableView(
            editTriggers=QTableView.NoEditTriggers,
        )
        self.tableview.setModel(self.tablemodel)
        self.tableview.selectionModel().selectionChanged.connect(
            self._invalidate
        )
        grid.addWidget(self.tableview, 1, 1)
        self.mainArea.layout().addLayout(grid)

    def set_results(self, results):
        """Set the input results."""

        self.clear()
        self.warning([0, 1])

        data = None
        if results is not None:
            if results.data is not None:
                data = results.data

        if data is not None and \
                not isinstance(data.domain.class_var,
                               Orange.data.DiscreteVariable):
            data = None
            results = None
            self.warning(
                0, "Confusion Matrix cannot be used for regression results.")

        self.results = results
        self.data = data

        if data is not None:
            class_values = data.domain.class_var.values
        elif results is not None:
            raise NotImplementedError

        if results is not None:
            nmodels, ntests = results.predicted.shape
            headers = class_values + [unicodedata.lookup("N-ARY SUMMATION")]

            # NOTE: The 'fitter_names' is set in 'Test Learners' widget.
            if hasattr(results, "fitter_names"):
                self.learners = results.fitter_names
            else:
                self.learners = ["L %i" % (i + 1) for i in range(nmodels)]

            self.tablemodel.setVerticalHeaderLabels(headers)
            self.tablemodel.setHorizontalHeaderLabels(headers)
            self.tablemodel.setRowCount(len(class_values) + 1)
            self.tablemodel.setColumnCount(len(class_values) + 1)
            self.selected_learner = [0]
            self._update()

    def clear(self):
        self.learners = []
        self.results = None
        self.data = None
        self.tablemodel.clear()

    def select_correct(self):
        selection = QItemSelection()
        n = self.tablemodel.rowCount()
        for i in range(n):
            index = self.tablemodel.index(i, i)
            selection.select(index, index)

        self.tableview.selectionModel().select(
            selection, QItemSelectionModel.ClearAndSelect
        )

    def select_wrong(self):
        selection = QItemSelection()
        n = self.tablemodel.rowCount()

        for i in range(n):
            for j in range(i + 1, n):
                index = self.tablemodel.index(i, j)
                selection.select(index, index)
                index = self.tablemodel.index(j, i)
                selection.select(index, index)

        self.tableview.selectionModel().select(
            selection, QItemSelectionModel.ClearAndSelect
        )

    def select_none(self):
        self.tableview.selectionModel().clear()

    def commit(self):
        if self.results and self.data:
            indices = self.tableview.selectedIndexes()
            indices = {(ind.row(), ind.column()) for ind in indices}
            actual = self.results.actual
            selected_learner = self.selected_learner[0]
            learner_name = self.learners[selected_learner]
            predicted = self.results.predicted[selected_learner]
            selected = [i for i, t in enumerate(zip(actual, predicted))
                        if t in indices]
            row_indices = self.results.row_indices[selected]

            extra = []
            class_var = self.data.domain.class_var
            metas = self.data.domain.metas

            if self.append_predictions:
                predicted = numpy.array(predicted[selected], dtype=object)
                extra.append(predicted.reshape(-1, 1))
                var = Orange.data.DiscreteVariable(
                    "{}({})".format(class_var.name, learner_name),
                    class_var.values
                )
                metas = metas + (var,)

            if self.append_probabilities and \
                    self.results.probabilities is not None:
                probs = self.results.probabilities[selected_learner, selected]
                extra.append(numpy.array(probs, dtype=object))
                pvars = [Orange.data.ContinuousVariable("p({})".format(value))
                         for value in class_var.values]
                metas = metas + tuple(pvars)

            X = self.data.X[row_indices]
            Y = self.data.Y[row_indices]
            M = self.data.metas[row_indices]

            M = numpy.hstack((M,) + tuple(extra))
            domain = Orange.data.Domain(
                self.data.domain.attributes,
                self.data.domain.class_vars,
                metas
            )

            data = Orange.data.Table.from_numpy(domain, X, Y, M)

        else:
            data = None

        self.send("Selected Data", data)
        self._invalidated = False

    def _invalidate(self):
        if self.autocommit:
            self.commit()
        else:
            self._invalidated = True

    def _learner_changed(self):
        # The selected learner has changed
        self._update()

    def _update(self):
        # Update the displayed confusion matrix
        if self.results is not None and self.selected_learner:
            index = self.selected_learner[0]
            cmatrix = confusion_matrix(self.results, index)
            colsum = cmatrix.sum(axis=0)
            rowsum = cmatrix.sum(axis=1)
            total = rowsum.sum()

            if self.selected_quantity == 0:
                value = lambda i, j: int(cmatrix[i, j])
            elif self.selected_quantity == 1:
                priors = numpy.outer(rowsum, colsum) / total
                value = lambda i, j: \
                    "{} / {:5.3f}".format(cmatrix[i, j], priors[i, j])
            elif self.selected_quantity == 2:
                value = lambda i, j: \
                    ("{:2.1f} %".format(100 * cmatrix[i, j] / colsum[i])
                     if colsum[i] else "N/A")
            elif self.selected_quantity == 3:
                value = lambda i, j: \
                    ("{:2.1f} %".format(100 * cmatrix[i, j] / rowsum[i])
                     if colsum[i] else "N/A")
            else:
                assert False

            model = self.tablemodel
            for i, row in enumerate(cmatrix):
                for j, _ in enumerate(row):
                    item = model.item(i, j)
                    if item is None:
                        item = QStandardItem()
                    item.setData(value(i, j), Qt.DisplayRole)
                    item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter)
                    item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)
                    model.setItem(i, j, item)

            font = model.invisibleRootItem().font()
            bold_font = QFont(font)
            bold_font.setBold(True)

            def sum_item(value):
                item = QStandardItem()
                item.setData(value, Qt.DisplayRole)
                item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter)
                item.setFlags(Qt.ItemIsEnabled)
                item.setFont(bold_font)
                return item

            N = len(colsum)
            for i in range(N):
                model.setItem(N, i, sum_item(int(colsum[i])))
                model.setItem(i, N, sum_item(int(rowsum[i])))

            model.setItem(N, N, sum_item(int(total)))
Пример #6
0
class LayerSelectionPage(QFrame):
    #TODO. Filtering, (visible) row selection, multi selection
    colparams = ((0,65,'Name'), (1,235,'Title'), (2,350,'Keywords'))
    XFER_BW = 40
    def __init__(self, parent=None):
        super(LayerSelectionPage, self).__init__(parent)
        self.parent = parent
        
        #convenience link
        self.confconn_link = self.parent.parent.confconn
        
        #flag top prevent read read action on keyword delete. New logic makes this redundant
        #self.keywordbypass = False

        QToolTip.setFont(QFont('SansSerif', 10))
        
        #label
        filterlabel = QLabel('Filter')
        availablelabel = QLabel('Available Layers')
        selectionlabel = QLabel('Layer Selections')
        keywordlabel = QLabel('Keyword')
        explainlabel = QLabel("Edit Group assignments using this dialog or to simply initialise the Layer-Config just click 'Finish'")
        
        #selection buttons
        chooseallbutton = QPushButton('>>')
        chooseallbutton.setFixedWidth(self.XFER_BW)
        chooseallbutton.clicked.connect(self.doChooseAllClickAction)
        
        choosebutton = QPushButton('>')
        choosebutton.setFixedWidth(self.XFER_BW)
        choosebutton.clicked.connect(self.doChooseClickAction)
        
        rejectbutton = QPushButton('<')
        rejectbutton.setFixedWidth(self.XFER_BW)
        rejectbutton.clicked.connect(self.doRejectClickAction)
        
        rejectallbutton = QPushButton('<<')
        rejectallbutton.setFixedWidth(self.XFER_BW)
        rejectallbutton.clicked.connect(self.doRejectAllClickAction)
        
        #operation buttons        
        finishbutton = QPushButton('Finish')
        finishbutton.setToolTip('Finish and Close layer selection dialog')
        finishbutton.clicked.connect(self.parent.close)
        
        resetbutton = QPushButton('Reset')
        resetbutton.font()
        resetbutton.setToolTip('Read Layer from LDS GetCapabilities request. Overwrites current Layer Config')       
        resetbutton.clicked.connect(self.doResetClickAction)
        
        self.available_sfpm = LDSSFPAvailableModel(self)
        self.selection_sfpm = LDSSFPSelectionModel(self)
        
        self.available_sfpm.setSourceModel(self.parent.available_model)
        self.selection_sfpm.setSourceModel(self.parent.selection_model)
        
        #textedits
        filteredit = QLineEdit('')
        filteredit.setToolTip('Filter Available-Layers pane (filter operates across Name and Title fields and accepts Regex expressions)')       
        filteredit.textChanged.connect(self.available_sfpm.setActiveFilter)
        
        self.keywordcombo = QComboBox()
        self.keywordcombo.setToolTip('Select or Add a unique identifier to be saved in layer config (keyword)')
        self.keywordcombo.addItems(list(self.confconn_link.assigned))
        self.keywordcombo.setEditable(True)
        self.keywordcombo.activated.connect(self.doKeyComboChangeAction)
        
        lgindex = self.confconn_link.getLayerGroupIndex(self.confconn_link.lgval,col=1)
        lgentry = self.confconn_link.lglist[lgindex] if LU.assessNone(lgindex) else None
        #keywordedit = self.keywordcombo.lineEdit().text().toUtf8().data().decode('utf8')# for writing
        #if no entry or layer indicated then blank 
        self.keywordcombo.lineEdit().setText('' if lgentry is None or lgentry[0]==LORG.LAYER else lgentry[1])#self.confconn_link.lgval)#TODO. group only
        
        #header
        headmodel = QStandardItemModel()
        headmodel.setHorizontalHeaderLabels([i[2] for i in self.colparams][:self.parent.available_model.columnCount()])
        
        headview1 = QHeaderView(Qt.Horizontal)
        headview1.setModel(headmodel)
        headview1.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) 
        
        headview2 = QHeaderView(Qt.Horizontal)
        headview2.setModel(headmodel)
        headview2.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)            

        #table
        self.available = QTableView()
        self.available.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.available.setSelectionMode(QAbstractItemView.MultiSelection)       
        
        self.selection = QTableView()
        self.selection.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.selection.setSelectionMode(QAbstractItemView.MultiSelection)
        
        #interesting, must set model after selection attributes but before headers else row selections/headers don't work properly
        self.available.setModel(self.available_sfpm)
        self.selection.setModel(self.selection_sfpm)
        
        self.available.setSortingEnabled(True)
        self.available.setHorizontalHeader(headview1)
        
        self.selection.setSortingEnabled(True)
        self.selection.setHorizontalHeader(headview2)

        for cp in self.colparams:
            self.available.setColumnWidth(cp[0],cp[1])
            self.selection.setColumnWidth(cp[0],cp[1])

        self.available.verticalHeader().setVisible(False)
        self.available.horizontalHeader().setVisible(True)
        
        self.selection.verticalHeader().setVisible(False)
        self.selection.horizontalHeader().setVisible(True)
        
        
        #layout  
        vbox00 = QVBoxLayout()
        vbox00.addWidget(availablelabel)
        vbox00.addWidget(self.available)
        
        vbox01 = QVBoxLayout()
        vbox01.addWidget(chooseallbutton)
        vbox01.addWidget(choosebutton)
        vbox01.addWidget(rejectbutton)
        vbox01.addWidget(rejectallbutton)
        
        vbox02 = QVBoxLayout()
        vbox02.addWidget(selectionlabel)
        vbox02.addWidget(self.selection)

        
        vbox10 = QVBoxLayout()
        vbox10.addWidget(filterlabel)
        vbox10.addWidget(filteredit)
        
        hbox12 = QHBoxLayout()
        hbox12.addWidget(keywordlabel)
        hbox12.addStretch(1)
        #hbox12.addWidget(inspbutton)
        #hbox12.addWidget(addbutton)
        #hbox12.addWidget(delbutton)
        
        vbox12 = QVBoxLayout()
        vbox12.addLayout(hbox12)
        vbox12.addWidget(self.keywordcombo)
                
        #00|01|02
        #10|11|12
        grid0 = QGridLayout()
        grid0.addLayout(vbox00,1,0)
        grid0.addLayout(vbox01,1,1)
        grid0.addLayout(vbox02,1,2)
        grid0.addLayout(vbox10,0,0)
        grid0.addLayout(vbox12,0,2)
        
        
        hbox2 = QHBoxLayout()
        hbox2.addWidget(resetbutton)
        hbox2.addStretch(1)
        hbox2.addWidget(explainlabel)
        hbox2.addWidget(finishbutton)
        #gbox1.setLayout(hbox2)
        
        
        
        vbox3 = QVBoxLayout()
        vbox3.addLayout(grid0)
        #vbox3.addLayout(hbox3)
        #vbox3.addWidget(line0)
        vbox3.addLayout(hbox2)
        
        self.setLayout(vbox3)


            
    def doChooseAllClickAction(self):
        '''Moves the lot to Selected'''
        #ktext = LU.recode(self.keywordcombo.lineEdit().text().toUtf8().data())
        ktext = LU.recode(LQ.readWidgetText(self.keywordcombo.lineEdit().text()))
        if not self.checkKeyword(ktext): return
        #------------------------------
        self.parent.signalModels(self.parent.STEP.PRE)
        #self.parent.selection_model.mdata += self.parent.available_model.mdata
        self.parent.selection_model.initData(self.confconn_link.complete)
        self.parent.available_model.initData([])
        self.parent.signalModels(self.parent.STEP.POST)
        #------------------------------
        self.parent.writeKeysToLayerConfig(ktext)
        #self.confconn_link.setupAssignedLayerList()
        if self.keywordcombo.findText(ktext) == -1:
            self.keywordcombo.addItem(ktext)
    
    def doChooseClickAction(self):
        '''Takes available selected and moves to selection'''
        #ktext = LU.recode(self.keywordcombo.lineEdit().text().toUtf8().data())
        ktext = LU.recode(LQ.readWidgetText(self.keywordcombo.lineEdit().text()))
        #ktext = str(self.keywordcombo.lineEdit().text())
        if not self.checkKeyword(ktext): return
        #------------------------------
        select = self.available.selectionModel()
        if select.hasSelection():
            self.transferSelectedRows(select.selectedRows(),self.available_sfpm,self.selection_sfpm)
            #------------------------------
            self.parent.writeKeysToLayerConfig(ktext)
            #self.confconn_link.assigned = self.confconn_link.setupAssignedLayerList()
            # -1 to indicate no index since 0,1,... are valid
            if self.keywordcombo.findText(ktext) == -1:
                self.keywordcombo.addItem(ktext)
        else:
            ldslog.warn('L2R > Transfer action without selection')        
        #TRACE#
        #pdb.set_trace()
        self.available.clearSelection()
          
        
    def transferSelectedRows(self,indices,from_model,to_model):
        tlist = []
        for proxymodelindex in indices:
            transfer = from_model.getData(proxymodelindex)
            tlist.append((proxymodelindex,transfer),)

        to_model.addData([t[1] for t in tlist])
        from_model.delData([t[0] for t in tlist])
        return tlist
            
    def doRejectClickAction(self):
        '''Takes available selected and moves to selection'''
        #ktext = LU.recode(self.keywordcombo.lineEdit().text().toUtf8().data())
        ktext = LU.recode(LQ.readWidgetText(self.keywordcombo.lineEdit().text()))
        if not self.checkKeyword(ktext): return
        #------------------------------
        select = self.selection.selectionModel()
        if select.hasSelection():
            tlist = self.transferSelectedRows(select.selectedRows(),self.selection_sfpm,self.available_sfpm)
            #------------------------------
            kindex = self.keywordcombo.findText(ktext)
            remainder = self.parent.deleteKeysFromLayerConfig([ll[1][0] for ll in tlist],ktext)
            if remainder > 0 and kindex == -1:
                #items+newkey -> add
                self.parent.writeKeysToLayerConfig(ktext)
                self.keywordcombo.addItem(ktext)
            elif remainder == 0 and kindex > -1:
                #empty+oldkey -> del
                self.keywordcombo.removeItem(kindex)
                self.keywordcombo.clearEditText()
        else:
            ldslog.warn('R2L < Transfer action without selection')
        #TRACE#
        #pdb.set_trace()
        self.selection.clearSelection()

                
    def doRejectAllClickAction(self):
        #ktext = LU.recode(self.keywordcombo.lineEdit().text().toUtf8().data())
        ktext = LU.recode(LQ.readWidgetText(self.keywordcombo.lineEdit().text()))
        if not self.checkKeyword(ktext): return
        #------------------------------
        self.parent.deleteKeysFromLayerConfig([ll[0] for ll in self.parent.selection_model.mdata],ktext)
        #------------------------------
        self.parent.signalModels(self.parent.STEP.PRE)
        #self.parent.available_model.mdata += self.parent.selection_model.mdata
        self.parent.available_model.initData(self.confconn_link.complete)
        self.parent.selection_model.initData([])
        self.parent.signalModels(self.parent.STEP.POST)        
        #------------------------------
        #self.confconn_link.setupAssignedLayerList()
        #self.keywordbypass = True
        self.keywordcombo.removeItem(self.keywordcombo.findText(ktext))
        self.keywordcombo.clearEditText()
        
    def doKeyComboChangeAction(self):
        '''Reset the available pane and if there is anything in the keyword box use this to init the selection pane'''
        #HACK
        #if self.keywordbypass:
        #    self.keywordbypass = False
        #    return
        #------------------------------
        #ktext = LU.recode(self.keywordcombo.lineEdit().text().toUtf8().data())
        ktext = LU.recode(LQ.readWidgetText(self.keywordcombo.lineEdit().text()))
        #------------------------------
        av_sl = self.parent.splitData(ktext,self.confconn_link.complete)
        #av_sl = self.parent.splitData(ktext,self.confconn_link.complete)
        self.parent.signalModels(self.parent.STEP.PRE)
        self.parent.available_model.initData(av_sl[0])
        self.parent.selection_model.initData(av_sl[1])
        self.parent.signalModels(self.parent.STEP.POST)
    
    def doResetClickAction(self):
        '''Dumps the LC and rebuilds from a fresh read of the caps doc'''
        #int warning (QWidget parent, QString title, QString text, QString button0Text, QString button1Text = QString(), QString button2Text = QString(), int defaultButtonNumber = 0, int escapeButtonNumber = -1)
        ans = QMessageBox.warning(self, "Reset","This action will overwrite your Layer Configuration using the current LDS settings (potentially adding new or removing layers). Continue?","Continue","Cancel")
        if ans:
            #Cancel
            ldslog.warn('Cancelling Reset operation')
            return
        #Continue
        ldslog.warn('Reset Layer Config')
        self.parent.resetLayers()
        self.keywordcombo.clear()

    def checkKeyword(self,ktext):
        '''Checks keyword isn't null and isn't part of the LDS supplied keywords'''
        if LU.assessNone(ktext) is None:
            QMessageBox.about(self, "Keyword Required","Please enter a Keyword to assign Layer(s) to")
            return False
        if ktext in self.confconn_link.reserved:
            QMessageBox.about(self, "Reserved Keyword","'{}' is a reserved keyword, please select again".format(ktext))
            return False
        return True
Пример #7
0
    class VizRank(OWWidget):
        name = "Rank projections (Scatter Plot)"

        want_control_area = False

        def __init__(self, parent_widget):
            super().__init__()
            self.parent_widget = parent_widget
            self.running = False
            self.progress = None
            self.k = 10

            self.projectionTable = QTableView()
            self.mainArea.layout().addWidget(self.projectionTable)
            self.projectionTable.setSelectionBehavior(QTableView.SelectRows)
            self.projectionTable.setSelectionMode(QTableView.SingleSelection)
            self.projectionTable.setSortingEnabled(True)
            self.projectionTableModel = QStandardItemModel(self)
            self.projectionTable.setModel(self.projectionTableModel)
            self.projectionTable.selectionModel().selectionChanged.connect(
                self.on_selection_changed)

            self.button = gui.button(self.mainArea,
                                     self,
                                     "Start evaluation",
                                     callback=self.toggle,
                                     default=True)
            self.resize(380, 512)
            self._initialize()

        def _initialize(self):
            self.running = False
            self.projectionTableModel.clear()
            self.projectionTableModel.setHorizontalHeaderLabels(
                ["Score", "Feature 1", "Feature 2"])
            self.projectionTable.setColumnWidth(0, 60)
            self.projectionTable.setColumnWidth(1, 120)
            self.projectionTable.setColumnWidth(2, 120)
            self.button.setText("Start evaluation")
            self.button.setEnabled(False)
            self.pause = False
            self.data = None
            self.attrs = []
            self.scores = []
            self.i, self.j = 0, 0
            if self.progress:
                self.progress.finish()
            self.progress = None

            self.information(0)
            if self.parent_widget.data:
                if not self.parent_widget.data.domain.class_var:
                    self.information(
                        0, "Data with a class variable is required.")
                    return
                if len(self.parent_widget.data.domain.attributes) < 2:
                    self.information(0,
                                     'At least 2 unique features are needed.')
                    return
                if len(self.parent_widget.data) < 2:
                    self.information(0, 'At least 2 instances are needed.')
                    return
                self.button.setEnabled(True)

        def on_selection_changed(self, selected, deselected):
            """Called when the ranks view selection changes."""
            a1 = selected.indexes()[1].data()
            a2 = selected.indexes()[2].data()
            self.parent_widget.update_attr(attributes=(a1, a2))

        def toggle(self):
            self.running ^= 1
            if self.running:
                self.button.setText("Pause")
                self.run()
            else:
                self.button.setText("Continue")
                self.button.setEnabled(False)

        def run(self):
            graph = self.parent_widget.graph
            y_full = self.parent_widget.data.Y
            if not self.attrs:
                self.attrs = self.score_heuristic()
            if not self.progress:
                self.progress = gui.ProgressBar(
                    self,
                    len(self.attrs) * (len(self.attrs) - 1) / 2)
            for i in range(self.i, len(self.attrs)):
                ind1 = graph.attribute_name_index[self.attrs[i]]
                for j in range(self.j, i):
                    if not self.running:
                        self.i, self.j = i, j
                        if not self.projectionTable.selectedIndexes():
                            self.projectionTable.selectRow(0)
                        self.button.setEnabled(True)
                        return
                    ind2 = graph.attribute_name_index[self.attrs[j]]
                    X = graph.scaled_data[[ind1, ind2], :]
                    valid = graph.get_valid_list([ind1, ind2])
                    X = X[:, valid].T
                    if X.shape[0] < self.k:
                        self.progress.advance()
                        continue
                    y = y_full[valid]
                    n_neighbors = min(self.k, len(X) - 1)
                    knn = NearestNeighbors(n_neighbors=n_neighbors).fit(X)
                    ind = knn.kneighbors(return_distance=False)
                    if self.parent_widget.data.domain.has_discrete_class:
                        score = np.sum(y[ind] == y.reshape(-1, 1)) / (
                            len(y_full) * n_neighbors)
                    else:
                        score = r2_score(y, np.mean(
                            y[ind], axis=1)) * (len(y) / len(y_full))
                    pos = bisect_left(self.scores, score)
                    self.projectionTableModel.insertRow(
                        len(self.scores) - pos, [
                            QStandardItem("{:.4f}".format(score)),
                            QStandardItem(self.attrs[j]),
                            QStandardItem(self.attrs[i])
                        ])
                    self.scores.insert(pos, score)
                    self.progress.advance()
                self.j = 0
            self.progress.finish()
            if not self.projectionTable.selectedIndexes():
                self.projectionTable.selectRow(0)
            self.button.setText("Finished")
            self.button.setEnabled(False)

        def score_heuristic(self):
            X = self.parent_widget.graph.scaled_data.T
            Y = self.parent_widget.data.Y
            dom = Domain(
                [ContinuousVariable(str(i)) for i in range(X.shape[1])],
                self.parent_widget.data.domain.class_vars)
            data = Table(dom, X, Y)
            relief = ReliefF if isinstance(dom.class_var,
                                           DiscreteVariable) else RReliefF
            weights = relief(n_iterations=100, k_nearest=self.k)(data)
            attrs = sorted(zip(
                weights,
                (x.name for x in self.parent_widget.data.domain.attributes)),
                           reverse=True)
            return [a for _, a in attrs]
Пример #8
0
class MainWindow(QMainWindow):
    """
        Initialization
    """
    def __init__(self, rulesModel, logoFnam, *args):
        QMainWindow.__init__(self, *args)
        
        self.rulesModel = rulesModel
        
        self.rulesModel.dataChanged.connect(self._statusRefresh)
        
        self.cancelled = True   # for to handle win close box the same as Cancel button
        
        self.mainHSplit = QSplitter(self)   # data | buttons
        self.mainHSplit.setChildrenCollapsible(False)
        self.setCentralWidget(self.mainHSplit)

        self.mainVSplit = QSplitter(Qt.Vertical)
        self.mainVSplit.setChildrenCollapsible(False)
        self.mainHSplit.addWidget(self.mainVSplit)
        
        self._drawRules()
        self.mainVSplit.addWidget(self.rulesView)
        self.condActSplit = QSplitter()
        self.condActSplit.setChildrenCollapsible(False)
        self._drawCondAct()
        self.mainVSplit.addWidget(self.condActSplit)
        # let rules view resize vertically two times faster than cond/action view
        self.rulesView.setSizeIncrement(self.rulesView.sizeIncrement().width(), 
                                        2 * self.condView.sizeIncrement().height())
        
        self._drawButtons(logoFnam)
        self.setStatusBar(QStatusBar())
        self.condView.horizontalHeader().setCascadingSectionResizes(True)
        self.rulesView.selectRow(0)
                                
    def _drawRules(self):
        self.rulesView = QTableView()
        self.rulesView.setModel(self.rulesModel)
        self.rulesView.setEditTriggers(QAbstractItemView.AllEditTriggers)
        self.rulesView.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.rulesView.setSelectionMode(QAbstractItemView.SingleSelection)
        self.rulesView.horizontalHeader().setStretchLastSection(True)
        self.rulesView.resizeColumnsToContents()
        #self.rulesView.verticalHeader().setMovable(True)  # row remapping - see QHeaderView.logicalIndex()
        #self.rulesView.verticalHeader().setCascadingSectionResizes(True)  # takes space from next row
        self.rulesView.selectionModel().currentRowChanged.connect(self._ruleRowChanged)
        self.rulesView.verticalHeader().sectionResized[int,int,int].connect(self._ruleRowHeightChanged)
        
    def _drawCondAct(self):
        if getattr(self, 'condGB', None):
            m_settings.setValue('spl_condAct', self.condActSplit.saveState())
            self.condGB.deleteLater() # or .destroy()
            del self.condGB
            self.actionGB.deleteLater()
            del self.actionGB
            
        row = self._ruleCurrRow()
        rcount = self.rulesModel.rowCount()
        
        self.condGB = QGroupBox(self.tr('Conditions'))
        self.condView = QTableView()
        conds = self.rulesModel.ruleConditions(row) if row in range(rcount) \
                else []
        self.condModel = ConditionsModel(conds, self.rulesModel)
        self.condModel.dataChanged.connect(self._codeFragChanged)
        self.condView.setModel(self.condModel)
        self.condTypeDelegate = ComboBoxDelegate(Condition._types._typeCaptions)
        self.condView.setItemDelegateForColumn(0, self.condTypeDelegate)
        self.condView.setEditTriggers(QAbstractItemView.AllEditTriggers)
        self.condView.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.condView.setSelectionMode(QAbstractItemView.SingleSelection)
        self.condView.horizontalHeader().setStretchLastSection(True)
        self.condView.resizeColumnsToContents()
        self.condView.selectionModel().currentRowChanged.connect(self._statusRefresh)
        vbox = QVBoxLayout()
        vbox.addWidget(self.condView)
        self.condGB.setLayout(vbox)
        self.condActSplit.addWidget(self.condGB)
        
        self.actionGB = QGroupBox(self.tr('Actions'))
        self.actionView = QTableView()   # parent = self.actionGB)
        actions = self.rulesModel.ruleActions(row) if row in range(rcount) \
                else []
        self.actionModel = ActionsModel(actions, self.rulesModel)
        self.actionModel.dataChanged.connect(self._codeFragChanged)
        self.actionView.setModel(self.actionModel)
        self.actionTypeDelegate = ComboBoxDelegate(Action._types._typeCaptions)
        self.actionView.setItemDelegateForColumn(0, self.actionTypeDelegate)
        self.actionView.setEditTriggers(QAbstractItemView.AllEditTriggers)
        self.actionView.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.actionView.setSelectionMode(QAbstractItemView.SingleSelection)
        self.actionView.horizontalHeader().setStretchLastSection(True)
        self.actionView.resizeColumnsToContents()
        self.actionView.selectionModel().currentRowChanged.connect(self._statusRefresh)
        vbox = QVBoxLayout()
        vbox.addWidget(self.actionView)
        self.actionGB.setLayout(vbox)
        self.condActSplit.addWidget(self.actionGB)
        
        self.condActSplit.restoreState(m_settings.value('spl_condAct').toByteArray())

        
    def _drawButton(self, vbox, caption, slot, ena = False):
        but = QPushButton(self.tr(caption))
        but.setEnabled(ena)
        but.clicked.connect(getattr(self, slot))
        vbox.addWidget(but)     # add to VBoxLayout
        return but
    
    def _drawButtons(self, logoFnam):
        gbox = QGroupBox()
        spol = QSizePolicy()
        spol.horizontalPolicy = QSizePolicy.Maximum
        gbox.setSizePolicy(spol)
        vbox = QVBoxLayout()
        
        if os.path.isfile(logoFnam):
            img = QPixmap(logoFnam)    #.scaled(64, 64)
            lblLogo = QLabel()
            lblLogo.setPixmap(img)
            lblLogo.setAlignment(Qt.AlignTop | Qt.AlignRight)
            vbox.addWidget(lblLogo)
            #vbox.addSpacing(3) 
        
        self.butSave = self._drawButton(vbox, "M&odify", 'closeSave')
        font = QFont()
        font.setBold(True)
        self.butSave.setFont(font)
        self.butCancel = self._drawButton(vbox, "Cancel", 'closeCancel', True)
        vbox.addSpacing(36)
        self.butAddRule = self._drawButton(vbox, "Add Rule", 'addRule', True)
        self.butCopyRule = self._drawButton(vbox, "Copy Rule", 'copyRule')
        self.butDelRule = self._drawButton(vbox, "Delete Rule", 'delRule')
        self.butMoveRuleUp = self._drawButton(vbox, "Move Rule Up", 'moveRuleUp')
        self.butMoveRuleDn = self._drawButton(vbox, "Move Rule Down", 'moveRuleDown')
        vbox.addSpacing(24)
        self.butAddCond = self._drawButton(vbox, "Add Condition", 'addCond')
        self.butDelCond = self._drawButton(vbox, "Delete Condition", 'delCond')
        vbox.addSpacing(15)
        self.butAddAction = self._drawButton(vbox, "Add Action", 'addAction')
        self.butDelAction = self._drawButton(vbox, "Delete Action", 'delAction')
        
        gbox.setLayout(vbox)
        self.mainHSplit.addWidget(gbox) 
    
    """
        Internal Bindings Signal Receivers
    """
    # main win close events
    # .. (cancel closing with event.ignore(); QMainWindow calls event.accept())       
    @pyqtSlot(QCloseEvent)
    def closeEvent(self, event):
        self._saveAppState()
        # save rules if not empty and user clicked Modified/Save button
        if self.rulesModel.rowCount() > 0 and not self.cancelled:
            text = self.rulesModel.getRawRules().validate()
            if text:
                self.cancelled = True
                QMessageBox.information(self, APP_TITLE, 
                                        self.tr("Validation failed because of:<p><p>") + text)
                event.ignore()
                return              #  RETURN - cancel app closing ######
            self.rulesModel.saveScript()
        # accept window closing
        QMainWindow.closeEvent(self, event)
        # quit application
        m_app.quit()
    @pyqtSlot()
    def _statusRefresh(self):       # dis/enable buttons, display view selections
        ruleRow = self._ruleCurrRow()
        condRow = self._condCurrRow()
        actionRow = self._actionCurrRow()
        self.butSave.setEnabled(self.rulesModel.isModified())
        ruleCnt = self.rulesModel.rowCount()
        self.butCopyRule.setEnabled(ruleRow >= 0)
        self.butDelRule.setEnabled(ruleRow >= 0)
        self.butMoveRuleUp.setEnabled(ruleRow > 0)
        self.butMoveRuleDn.setEnabled(ruleRow >= 0 and ruleRow + 1 < ruleCnt)
        self.butAddCond.setEnabled(ruleRow >= 0)
        self.butDelCond.setEnabled(condRow >= 0)  
        self.butAddAction.setEnabled(ruleRow >= 0)
        self.butDelAction.setEnabled(actionRow >= 0)
        # display currently selected list rows in the status bar - if empty
        if ruleRow >= 0 and False:    # replace False with ~self.statusBar().isEmpty()?!?!?
            text = str(self.tr("Selected Rule: {ruleI}"))\
                .format(ruleI = ruleRow + 1)
            if condRow >= 0:
                text += "      " \
                    + str(self.tr("Selected Condition: {typeI}"))\
                    .format(typeI = condRow + 1)
            if actionRow >= 0:
                text += "      " \
                    + str(self.tr("Selected Action: {typeI}"))\
                    .format(typeI = actionRow + 1)
            self.statusBar().showMessage(text, 3000)
    @pyqtSlot(int,int,int)
    def _ruleRowHeightChanged(self, section, oldsize, newsize):
        hdr = self.rulesView.verticalHeader()
        for row in range(hdr.count()):
            if row != section:
                hdr.resizeSection(row, newsize)
    @pyqtSlot()
    def _ruleRowChanged(self):
        self._drawCondAct()
        self._statusRefresh()
    @pyqtSlot()
    def _codeFragChanged(self):     # refresh the rules list columns Conditions and Actions
        row = self._ruleCurrRow()
        leftColIndex = self.rulesModel.index(row, 2, QModelIndex())
        rightColIndex = self.rulesModel.index(row, 3, QModelIndex())
        self.rulesView.dataChanged(leftColIndex, rightColIndex)
        self._statusRefresh()
        
    """
        User Action Signal Receivers
    """
    @pyqtSlot()
    def closeSave(self):
        self.cancelled = False
        self.close()
    @pyqtSlot()
    def closeCancel(self):
        self.cancelled = True
        self.close()
    @pyqtSlot()
    def addRule(self):
        row = self._ruleCurrRow()
        self.rulesModel.insertRow(row)
        self.rulesView.selectRow(row)
        self._statusRefresh()
    @pyqtSlot()
    def copyRule(self):
        row = self._ruleCurrRow()
        self.rulesModel.setSourceRowForNextAdd(row)
        self.rulesModel.insertRow(row)
        self.rulesView.selectRow(row)
        self._statusRefresh()
    @pyqtSlot()
    def delRule(self):
        self.rulesModel.removeRow(self._ruleCurrRow())
        self._statusRefresh()
    @pyqtSlot()
    def moveRuleUp(self):
        row = self._ruleCurrRow()
        self.rulesModel.moveRule(row, -1)
        self._statusRefresh()
    @pyqtSlot()
    def moveRuleDown(self):
        row = self._ruleCurrRow()
        self.rulesModel.moveRule(row)
        self._statusRefresh()
    @pyqtSlot()
    def addCond(self):
        cnt = self.condModel.rowCount()
        self.condModel.insertRow(cnt)
        self.condView.selectRow(cnt)
        self._statusRefresh()
    @pyqtSlot()
    def delCond(self):
        self.condModel.removeRow(self._condCurrRow())
        self._statusRefresh()
    @pyqtSlot()
    def addAction(self):
        cnt = self.actionModel.rowCount()
        self.actionModel.insertRow(cnt)
        self.actionView.selectRow(cnt)
        self._statusRefresh()
    @pyqtSlot()
    def delAction(self):
        self.actionModel.removeRow(self._actionCurrRow())
        self._statusRefresh()
    
    """
        Helping Methods
    """
    def _ruleCurrRow(self):
        #idxs = self.rulesView.selectedIndexes()
        #return idxs[0].row() if idxs else -1
        return self.rulesView.currentIndex().row()
    def _condCurrRow(self):
        return self.condView.currentIndex().row()
    def _actionCurrRow(self):
        return self.actionView.currentIndex().row()
    
    # main win save/restore
    def _saveAppState(self):
        m_app.processEvents()
        # save win geometry and splitter positions
        _UI_SAVE(self, 'win_geometry')
        _UI_SAVE(self.mainHSplit, 'spl_mainH')
        _UI_SAVE(self.mainVSplit, 'spl_mainV')
        _UI_SAVE(self.condActSplit, 'spl_condAct')
        #_UI_SAVE(self.condView.horizontalHeader(), 'tvh_condHdr')
    def _restoreAppState(self):
        try:    # will fail on first app startup after installation
            # restore last win position, -size and 3 splitter positions
            _UI_RESTORE(self, 'win_geometry')
            _UI_RESTORE(self.mainHSplit, 'spl_mainH')
            _UI_RESTORE(self.mainVSplit, 'spl_mainV')
            _UI_RESTORE(self.condActSplit, 'spl_condAct')
            #_UI_RESTORE(self.condView.horizontalHeader(), 'tvh_condHdr')
        except: # first start
            screenWidth = QApplication.desktop().width()
            screenHeight = QApplication.desktop().height()
            self.setGeometry(screenWidth / 9, screenHeight / 12,
                            screenWidth / 1.26, screenHeight / 1.56)
Пример #9
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(
            "")
Пример #10
0
from PyQt4.QtSql import QSqlQueryModel, QSqlDatabase
from PyQt4.QtGui import QApplication, QListView, QTableView
import sys

app = QApplication(sys.argv)

db = QSqlDatabase.addDatabase("QMYSQL")
db.setHostName("localhost")
db.setDatabaseName("app")
db.setUserName("root")
db.setPassword("")
db.open()

projectModel = QSqlQueryModel()
projectModel.setQuery("select name from customers", db)

projectView = QTableView()
projectView.setModel(projectModel)

projectView.show()

model = projectView.model()
indexes = projectView.selectionModel().currentIndex().row()

app.exec_()
Пример #11
0
from PyQt4.QtSql import QSqlQueryModel,QSqlDatabase
from PyQt4.QtGui import QApplication,QListView,QTableView
import sys

app = QApplication(sys.argv)

db = QSqlDatabase.addDatabase("QMYSQL")
db.setHostName("localhost")
db.setDatabaseName("app")
db.setUserName("root")
db.setPassword("")
db.open()

projectModel = QSqlQueryModel()
projectModel.setQuery("select name from customers",db)

projectView = QTableView()
projectView.setModel(projectModel)

projectView.show()

model = projectView.model()
indexes = projectView.selectionModel().currentIndex().row()

app.exec_()

Пример #12
0
class OWMPR(OWWidget):
    name = 'ModelMap Projection Rank'
    description = 'Ranking projections by estimating projection quality'
    icon = "icons/ModelMap.svg"

    inputs = [('Data', Table, 'set_data', Default)]
    outputs = [('Features', AttributeList)]
    want_main_area = False
    settingsHandler = DomainContextHandler()

    variable_changed = Signal()

    def __init__(self):
        super().__init__()
        self.data = None
        self.progress = None

        self.infoa = gui.widgetLabel(self.controlArea, "No data loaded.")

        self.projectionTable = QTableView()
        self.controlArea.layout().addWidget(self.projectionTable)
        self.projectionTable.setSelectionBehavior(QTableView.SelectRows)
        self.projectionTable.setSelectionMode(QTableView.SingleSelection)
        self.projectionTable.setSortingEnabled(True)

        self.projectionTableModel = QStandardItemModel(self)
        self.projectionTableModel.setHorizontalHeaderLabels(
            ["P-Index", "", ""])
        self.projectionTable.setModel(self.projectionTableModel)

        self.projectionTable.setColumnWidth(0, 90)
        self.projectionTable.sortByColumn(0, Qt.DescendingOrder)
        self.projectionTable.selectionModel().selectionChanged.connect(
            self.on_selection_changed)

        gui.button(self.controlArea,
                   self,
                   "Rank Projections",
                   callback=self.rank,
                   default=True)
        self.resize(370, 600)

    def set_data(self, data):
        self.data = data
        self.infoa.setText("Data set: {}".format(data.name) if self.
                           data else "No data loaded.")

    def rank(self):
        if self.progress:
            return

        disc = Orange.feature.discretization.EqualWidth(n=10)

        ndomain = Orange.data.Domain([
            disc(self.data, attr)
            if type(attr) == Orange.data.variable.ContinuousVariable else attr
            for attr in self.data.domain.attributes
        ], self.data.domain.class_vars)

        t = self.data.from_table(ndomain, self.data)

        attrs = t.domain.attributes

        tables = {}
        l = 0
        self.progress = gui.ProgressBar(self,
                                        len(attrs) * (len(attrs) - 1) / 2)
        for i in range(len(attrs)):
            for j in range(i):
                ct = np.array(
                    contingency.get_contingency(t, attrs[j], attrs[i]))
                pindex, _, _ = p_index(ct)
                tables[i, j] = ct

                item = QStandardItem()
                item.setData(float(pindex), Qt.DisplayRole)
                self.projectionTableModel.setItem(l, 0, item)

                item = QStandardItem()
                item.setData(attrs[i].name, Qt.DisplayRole)
                self.projectionTableModel.setItem(l, 1, item)

                item = QStandardItem()
                item.setData(attrs[j].name, Qt.DisplayRole)
                self.projectionTableModel.setItem(l, 2, item)

                self.progress.advance()
                l += 1

        self.progress.finish()
        self.progress = None

    def on_selection_changed(self, selected, deselected):
        """Called when the ranks view selection changes."""
        a1 = selected.indexes()[1].data().replace('D_', '')
        a2 = selected.indexes()[2].data().replace('D_', '')
        d = self.data.domain
        self.send("Features", AttributeList([d[a1], d[a2]]))
Пример #13
0
class OWConfusionMatrix(widget.OWWidget):
    name = "Confusion Matrix"
    description = "Shows a confusion matrix."
    icon = "icons/ConfusionMatrix.svg"
    priority = 1001

    inputs = [{
        "name": "Evaluation Results",
        "type": Orange.evaluation.Results,
        "handler": "set_results"
    }]
    outputs = [{"name": "Selected Data", "type": Orange.data.Table}]

    quantities = [
        "Number of instances", "Proportion of predicted",
        "Proportion of actual"
    ]

    selected_learner = settings.Setting([])
    selected_quantity = settings.Setting(0)
    append_predictions = settings.Setting(True)
    append_probabilities = settings.Setting(False)
    autocommit = settings.Setting(True)

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

        self.data = None
        self.results = None
        self.learners = []

        box = gui.widgetBox(self.controlArea, "Learners")

        self.learners_box = gui.listBox(box,
                                        self,
                                        "selected_learner",
                                        "learners",
                                        callback=self._learner_changed)
        box = gui.widgetBox(self.controlArea, "Show")

        gui.comboBox(box,
                     self,
                     "selected_quantity",
                     items=self.quantities,
                     callback=self._update)

        box = gui.widgetBox(self.controlArea, "Select")

        gui.button(box,
                   self,
                   "Correct",
                   callback=self.select_correct,
                   autoDefault=False)
        gui.button(box,
                   self,
                   "Misclassified",
                   callback=self.select_wrong,
                   autoDefault=False)
        gui.button(box,
                   self,
                   "None",
                   callback=self.select_none,
                   autoDefault=False)

        self.outputbox = box = gui.widgetBox(self.controlArea, "Output")
        gui.checkBox(box,
                     self,
                     "append_predictions",
                     "Predictions",
                     callback=self._invalidate)
        gui.checkBox(box,
                     self,
                     "append_probabilities",
                     "Probabilities",
                     callback=self._invalidate)

        gui.auto_commit(self.controlArea, self, "autocommit", "Send Data",
                        "Auto send is on")

        grid = QGridLayout()
        grid.setContentsMargins(0, 0, 0, 0)
        grid.addWidget(QLabel("Predicted"), 0, 1, Qt.AlignCenter)
        grid.addWidget(VerticalLabel("Actual Class"), 1, 0, Qt.AlignCenter)

        self.tablemodel = QStandardItemModel()
        self.tableview = QTableView(editTriggers=QTableView.NoEditTriggers)
        self.tableview.setModel(self.tablemodel)
        self.tableview.selectionModel().selectionChanged.connect(
            self._invalidate)
        grid.addWidget(self.tableview, 1, 1)
        self.mainArea.layout().addLayout(grid)

    def set_results(self, results):
        """Set the input results."""

        self.clear()
        self.warning([0, 1])

        data = None
        if results is not None:
            if results.data is not None:
                data = results.data

        if data is not None and \
                not isinstance(data.domain.class_var,
                               Orange.data.DiscreteVariable):
            data = None
            results = None
            self.warning(
                0, "Confusion Matrix cannot be used for regression results.")

        self.results = results
        self.data = data

        if data is not None:
            class_values = data.domain.class_var.values
        elif results is not None:
            raise NotImplementedError

        if results is not None:
            nmodels, ntests = results.predicted.shape
            headers = class_values + [unicodedata.lookup("N-ARY SUMMATION")]

            # NOTE: The 'learner_names' is set in 'Test Learners' widget.
            if hasattr(results, "learner_names"):
                self.learners = results.learner_names
            else:
                self.learners = ["L %i" % (i + 1) for i in range(nmodels)]

            self.tablemodel.setVerticalHeaderLabels(headers)
            self.tablemodel.setHorizontalHeaderLabels(headers)
            self.tablemodel.setRowCount(len(class_values) + 1)
            self.tablemodel.setColumnCount(len(class_values) + 1)
            self.selected_learner = [0]
            self._update()

    def clear(self):
        self.results = None
        self.data = None
        self.tablemodel.clear()
        # Clear learners last. This action will invoke `_learner_changed`
        # method
        self.learners = []

    def select_correct(self):
        selection = QItemSelection()
        n = self.tablemodel.rowCount()
        for i in range(n):
            index = self.tablemodel.index(i, i)
            selection.select(index, index)

        self.tableview.selectionModel().select(
            selection, QItemSelectionModel.ClearAndSelect)

    def select_wrong(self):
        selection = QItemSelection()
        n = self.tablemodel.rowCount()

        for i in range(n):
            for j in range(i + 1, n):
                index = self.tablemodel.index(i, j)
                selection.select(index, index)
                index = self.tablemodel.index(j, i)
                selection.select(index, index)

        self.tableview.selectionModel().select(
            selection, QItemSelectionModel.ClearAndSelect)

    def select_none(self):
        self.tableview.selectionModel().clear()

    def commit(self):
        if self.results is not None and self.data is not None \
                and self.selected_learner:
            indices = self.tableview.selectedIndexes()
            indices = {(ind.row(), ind.column()) for ind in indices}
            actual = self.results.actual
            selected_learner = self.selected_learner[0]
            learner_name = self.learners[selected_learner]
            predicted = self.results.predicted[selected_learner]
            selected = [
                i for i, t in enumerate(zip(actual, predicted)) if t in indices
            ]
            row_indices = self.results.row_indices[selected]

            extra = []
            class_var = self.data.domain.class_var
            metas = self.data.domain.metas

            if self.append_predictions:
                predicted = numpy.array(predicted[selected], dtype=object)
                extra.append(predicted.reshape(-1, 1))
                var = Orange.data.DiscreteVariable(
                    "{}({})".format(class_var.name, learner_name),
                    class_var.values)
                metas = metas + (var, )

            if self.append_probabilities and \
                    self.results.probabilities is not None:
                probs = self.results.probabilities[selected_learner, selected]
                extra.append(numpy.array(probs, dtype=object))
                pvars = [
                    Orange.data.ContinuousVariable("p({})".format(value))
                    for value in class_var.values
                ]
                metas = metas + tuple(pvars)

            X = self.data.X[row_indices]
            Y = self.data.Y[row_indices]
            M = self.data.metas[row_indices]
            row_ids = self.data.ids[row_indices]

            M = numpy.hstack((M, ) + tuple(extra))
            domain = Orange.data.Domain(self.data.domain.attributes,
                                        self.data.domain.class_vars, metas)
            data = Orange.data.Table.from_numpy(domain, X, Y, M)
            data.ids = row_ids
            data.name = learner_name

        else:
            data = None

        self.send("Selected Data", data)

    def _invalidate(self):
        self.commit()

    def _learner_changed(self):
        # The selected learner has changed
        self._update()
        self._invalidate()

    def _update(self):
        # Update the displayed confusion matrix
        if self.results is not None and self.selected_learner:
            index = self.selected_learner[0]
            cmatrix = confusion_matrix(self.results, index)
            colsum = cmatrix.sum(axis=0)
            rowsum = cmatrix.sum(axis=1)
            total = rowsum.sum()

            if self.selected_quantity == 0:
                value = lambda i, j: int(cmatrix[i, j])
            elif self.selected_quantity == 1:
                value = lambda i, j: \
                    ("{:2.1f} %".format(100 * cmatrix[i, j] / colsum[i])
                     if colsum[i] else "N/A")
            elif self.selected_quantity == 2:
                value = lambda i, j: \
                    ("{:2.1f} %".format(100 * cmatrix[i, j] / rowsum[i])
                     if colsum[i] else "N/A")
            else:
                assert False

            model = self.tablemodel
            for i, row in enumerate(cmatrix):
                for j, _ in enumerate(row):
                    item = model.item(i, j)
                    if item is None:
                        item = QStandardItem()
                    item.setData(value(i, j), Qt.DisplayRole)
                    item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter)
                    item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)
                    model.setItem(i, j, item)

            font = model.invisibleRootItem().font()
            bold_font = QFont(font)
            bold_font.setBold(True)

            def sum_item(value):
                item = QStandardItem()
                item.setData(value, Qt.DisplayRole)
                item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter)
                item.setFlags(Qt.ItemIsEnabled)
                item.setFont(bold_font)
                return item

            N = len(colsum)
            for i in range(N):
                model.setItem(N, i, sum_item(int(colsum[i])))
                model.setItem(i, N, sum_item(int(rowsum[i])))

            model.setItem(N, N, sum_item(int(total)))
Пример #14
0
class QueueDialog(Window):
    def __init__(self, base):
        Window.__init__(self, base, i18n.get('messages_queue'))
        self.setFixedSize(500, 400)
        self.last_timestamp = None
        self.showed = False

        self.list_ = QTableView()
        self.list_.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.list_.clicked.connect(self.__account_clicked)

        self.caption = QLabel()
        self.caption.setWordWrap(True)
        self.caption.setAlignment(Qt.AlignCenter)

        self.estimated_time = QLabel()
        self.estimated_time.setWordWrap(True)
        self.estimated_time.setAlignment(Qt.AlignCenter)

        self.delete_button = QPushButton(i18n.get('delete'))
        self.delete_button.setEnabled(False)
        self.delete_button.setToolTip(i18n.get('delete_selected_message'))
        self.delete_button.clicked.connect(self.__delete_message)

        self.clear_button = QPushButton(i18n.get('delete_all'))
        self.clear_button.setEnabled(False)
        self.clear_button.setToolTip(i18n.get('delete_all_messages_in_queue'))
        self.clear_button.clicked.connect(self.__delete_all)

        button_box = QHBoxLayout()
        button_box.addStretch(1)
        button_box.addWidget(self.clear_button)
        button_box.addWidget(self.delete_button)

        layout = QVBoxLayout()
        layout.addWidget(self.list_, 1)
        layout.addWidget(self.caption)
        layout.addWidget(self.estimated_time)
        layout.addLayout(button_box)
        layout.setSpacing(5)
        layout.setContentsMargins(5, 5, 5, 5)
        self.setLayout(layout)

    def __account_clicked(self, point):
        self.delete_button.setEnabled(True)
        self.clear_button.setEnabled(True)

    def __delete_message(self):
        self.__disable()
        selection = self.list_.selectionModel()
        index = selection.selectedIndexes()[0]
        message = i18n.get('delete_message_from_queue_confirm')
        confirmation = self.base.show_confirmation_message(
            i18n.get('confirm_delete'), message)
        if not confirmation:
            self.__enable()
            return
        self.base.delete_message_from_queue(index.row())

    def __delete_all(self):
        self.__disable()
        message = i18n.get('clear_message_queue_confirm')
        confirmation = self.base.show_confirmation_message(
            i18n.get('confirm_delete'), message)
        if not confirmation:
            self.__enable()
            return
        self.base.clear_queue()

    def __enable(self):
        self.list_.setEnabled(True)
        self.delete_button.setEnabled(False)
        if len(self.base.core.list_statuses_queue()) > 0:
            self.clear_button.setEnabled(True)
        else:
            self.clear_button.setEnabled(False)

    def __disable(self):
        self.list_.setEnabled(False)
        self.delete_button.setEnabled(False)
        self.clear_button.setEnabled(False)

    def __on_timeout(self):
        now = int(time.time())
        interval = self.base.core.get_queue_interval() * 60
        if self.last_timestamp:
            est_time = ((self.last_timestamp + interval) - now) / 60
        else:
            est_time = 0

        humanized_est_time = self.base.humanize_time_intervals(est_time)
        next_message = ' '.join(
            [i18n.get('next_message_should_be_posted_in'), humanized_est_time])

        if len(self.base.core.list_statuses_queue()) == 0:
            self.estimated_time.setText('')
        else:
            self.estimated_time.setText(next_message)

    def start(self):
        self.timer = QTimer()
        self.timer.timeout.connect(self.__on_timeout)
        self.timer.start(60000)

    def closeEvent(self, event=None):
        if event:
            event.ignore()
        self.hide()
        self.showed = False

    def show(self):
        if self.showed:
            self.raise_()
            return

        self.update()
        Window.show(self)
        self.showed = True

    def update(self):
        model = QStandardItemModel()
        model.setHorizontalHeaderItem(0, QStandardItem(i18n.get('account')))
        model.setHorizontalHeaderItem(1, QStandardItem(i18n.get('message')))
        self.list_.setModel(model)

        now = int(time.time())
        interval = self.base.core.get_queue_interval() * 60
        if self.last_timestamp:
            est_time = ((self.last_timestamp + interval) - now) / 60
        else:
            est_time = 0

        row = 0
        for status in self.base.core.list_statuses_queue():
            username = get_username_from(status.account_id)
            protocol_image = "%s.png" % get_protocol_from(status.account_id)
            item = QStandardItem(QString.fromUtf8(username))
            item.setIcon(QIcon(self.base.load_image(protocol_image, True)))
            model.setItem(row, 0, item)
            model.setItem(row, 1, QStandardItem(QString.fromUtf8(status.text)))
            row += 1

        humanized_interval = self.base.humanize_time_intervals(
            self.base.core.get_queue_interval())
        humanized_est_time = self.base.humanize_time_intervals(est_time)

        warning = i18n.get('messages_will_be_send') % humanized_interval
        next_message = ' '.join(
            [i18n.get('next_message_should_be_posted_in'), humanized_est_time])
        self.caption.setText(warning)

        if row == 0:
            self.estimated_time.setText('')
        else:
            self.estimated_time.setText(next_message)

        self.list_.horizontalHeader().setResizeMode(1, QHeaderView.Stretch)
        self.list_.resizeColumnsToContents()

        self.__enable()

    def update_timestamp(self):
        if len(self.base.core.list_statuses_queue()) > 0:
            self.last_timestamp = int(time.time())
        else:
            self.last_timestamp = None
Пример #15
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()
class ComponentSearchForm():

    data_source = None   
    related_mashups = None
    widget = None
    table = None
    add_btn = None
    graph_form = None
    highlighted_api = None
    highlighted_mashup = None
    categoryWindow = None
    dataSetListWdiget = None
    climateData = None
    
    def show_main_window(self):
        # Get datasets from server
        data = json.load(urllib2.urlopen(RECO_API_SERVER_ADDR + "/getAllDataSets/"))
        # self.climateData = self.loadClimateDataSet(data)
        self.climateData = self.parseServerData(data)

        self.graph_form = matplotlibWidget()
        if self.widget:
            self.widget.destroy()
            self.widget = None;
        self.widget = QWidget()
        self.widget.setMinimumSize(1000, 900)
        self.widget.setWindowTitle("Recommendation PlugIn")
        margin = 30

        # Search Feature
        self.textboxLabel = QLabel(self.widget)
        self.textboxLabel.setText("Describe your goals:")
        self.textboxLabel.move(30, 20)
        self.textboxLabel.show
        self.textbox = QTextEdit(self.widget)
        self.textbox.move(30, 45)
        self.textbox.setFixedWidth(300)
        self.textbox.setFixedHeight(28)

        btn_api = QtGui.QPushButton("Recommend Services", self.widget)
        btn_api.move(30, 80)

        btn_mashup = QtGui.QPushButton("Recommend Workflows", self.widget)
        btn_mashup.move(230, 80)

        btn_api.clicked.connect(self.api_button_clicked)
        btn_mashup.clicked.connect(self.mashups_button_clicked)

        self.table = QTableView(self.widget)
        self.table.clicked.connect(self.table_clicked)
        self.table.setMinimumSize(600, 300)
        self.table.resizeColumnsToContents()
        self.table.move(30, 120)

        # Top Service
        self.textboxLabel = QLabel("Top Datasets (Usage)", self.widget)
        self.textboxLabel.move(650, 20)
        self.textboxLabel.show

        self.listWidget = QListWidget(self.widget)
        topDatasets = json.load(urllib2.urlopen(RECO_API_SERVER_ADDR + "/getTop10UsedDataset/"))
        for topDataset in topDatasets:
            id = int(topDataset["datasetID"])
            item = QListWidgetItem("{} ({})".format(self.climateData[id]["name"], topDataset["usage"]))
            item.setData(Qt.UserRole,self.climateData[id])
            self.listWidget.addItem(item)
        self.listWidget.move(650, 45)
        self.listWidget.resize(280, 380)
        self.listWidget.show()
        self.listWidget.clicked.connect(lambda: self.dataset_clicked(\
            self.listWidget.currentItem().data(Qt.UserRole)))


        # Username input box and button for generating recommendations
        userTopOffset = 430
        self.textboxLabel = QLabel("Enter username for dataset recommendations:", self.widget)
        self.textboxLabel.move(30, userTopOffset)
        self.textboxLabel.show()

        self.userTextbox = QTextEdit(self.widget)
        self.userTextbox.move(30, userTopOffset + 30)
        self.userTextbox.setFixedWidth(200)
        self.userTextbox.setFixedHeight(28)

        userBtn = QPushButton("Recommend Datasets", self.widget)
        userBtn.move(30 + self.userTextbox.width() + 10, userTopOffset + 30)
	#print RECO_API_SERVER_ADDR + "/getTop5RecommendationByUserName/"
	    
	    ## Jan.20 2016 
	    ##  Change the API names here by shenggu 
	    ##  According to github.com/cmusv-sc/RecommendationAPIs
	    ##
        userBtn.clicked.connect(lambda: self.getRecommendations(RECO_API_SERVER_ADDR + "/getTopKContentBasedCFRecommendedDatasetByUsername",
            self.recListFeature))
        userBtn.clicked.connect(lambda: self.getRecommendations(RECO_API_SERVER_ADDR + "/getTopKItemBasedCFRecommendedDatasetByUsername",
            self.recListItem))
        userBtn.clicked.connect(lambda: self.getRecommendations(RECO_API_SERVER_ADDR + "/getTopKUserBasedCFRecommendedDatasetByUsername",
            self.recListUser))
        userBtn.show()

        # Test QlineEdit
        # self.userTextbox2 = QLineEdit(self.widget)
        # self.userTextbox.move(200, userTopOffset + 30)
        # self.userTextbox.setFixedWidth(200)
        # self.userTextbox.setFixedHeight(28)

        # Feature Recommendations
        recTopOffset = 500
        self.textboxLabel = QLabel("Feature Recommendations", self.widget)
        self.textboxLabel.move(30, recTopOffset)
        self.textboxLabel.show()

        self.recListFeature = QListWidget(self.widget)
        self.recListFeature.move(30, recTopOffset + 30)
        self.recListFeature.resize(280, 250)
        self.recListFeature.show()

        # Item-based Recommendations
        self.textboxLabel = QLabel("Item-based Recommendations", self.widget)
        self.textboxLabel.move(340, recTopOffset)
        self.textboxLabel.show

        self.recListItem = QListWidget(self.widget)
        self.recListItem.move(340, recTopOffset + 30)
        self.recListItem.resize(280, 250)
        self.recListItem.show()

        # User-based Recommendations
        self.textboxLabel = QLabel("User-based Recommendations", self.widget)
        self.textboxLabel.move(650, recTopOffset)
        self.textboxLabel.show

        self.recListUser = QListWidget(self.widget)
        self.recListUser.move(650, recTopOffset + 30)
        self.recListUser.resize(280, 250)
        self.recListUser.show()

        # Categories
        categoryTopOffset = 300
        self.textboxLabel = QLabel("Categories", self.widget)
        self.textboxLabel.move(30, recTopOffset + categoryTopOffset)
        self.textboxLabel.show

        button1 = QPushButton("By Agency", self.widget)
        button1.clicked.connect(lambda: self.listCategory_clicked("agency"))
        button1.move(30, recTopOffset + categoryTopOffset + 30)
        button1.show()

        button2 = QPushButton("By Instrument", self.widget)
        button2.clicked.connect(lambda: self.listCategory_clicked("instrument"))
        button2.move(margin + button1.width() + 20, recTopOffset + categoryTopOffset + 30)
        button2.show()

        button3 = QPushButton("By Data Source Input", self.widget)
        button3.clicked.connect(lambda: self.listCategory_clicked("input"))
        button3.move(margin + button1.width() + button2.width() + 40, recTopOffset + categoryTopOffset + 30)
        button3.show()

        # Show and move widget
        self.widget.move(QtGui.QApplication.desktop().screen().rect().center() - \
            self.widget.rect().center())
        self.widget.show()

        # Service and workflow recommendation
        self.add_btn = QPushButton("Add to Palette", self.widget)
        self.add_btn.clicked.connect(self.add_new_api)
        self.add_btn.hide()
        self.add_btn.setFixedWidth(160)
        self.add_btn.move(470, 20)
        
        self.recommendLabel = QLabel("Also Used", self.widget)
        self.recommendLabel.hide()
        self.recommendLabel.setFixedWidth(160)
        self.recommendLabel.move(470, 50)
        
        self.switch_btn_apis = QPushButton("Related Workflows", self.widget)
        self.switch_btn_apis.clicked.connect(self._show_related_apis)
        self.switch_btn_apis.hide()
        self.switch_btn_apis.setFixedWidth(160)
        self.switch_btn_apis.move(470, 80)
        
        self.switch_btn_mashups = QPushButton("Related Modules", self.widget)
        self.switch_btn_mashups.clicked.connect(self._show_related_mashups)
        self.switch_btn_mashups.hide()
        self.switch_btn_mashups.setFixedWidth(160)
        self.switch_btn_mashups.move(470, 80)

    def printMessage(self):
        print "testing"

    def __init__(self, parent=None):
        self.data_source = DataSource()
    
    def getRecommendations(self, url, listWidget):
        # http GET request
        username = str(self.userTextbox.toPlainText())
        url = url + "?username=kzhang&top_num=5" #  + username
        print url
        results = json.load(urllib2.urlopen(url))
        
        # Update recommendation list
        listWidget.clear()
        for result in results:
            dataset = self.climateData[int(result["datasetID"])]
            item = QListWidgetItem(dataset["name"])
            item.setData(Qt.UserRole, dataset)
            listWidget.addItem(item)

        listWidget.clicked.connect(lambda: self.dataset_clicked(\
            listWidget.currentItem().data(Qt.UserRole)))

    def listCategory_clicked(self, category):
        self.categoryWindow = QWidget()
        c = self.categoryWindow
        c.setWindowTitle("Search dataset by category")
        c.setMinimumSize(600, 500)
        
        # Category list showing all posible options
        label1 = QLabel("Options by {0}:".format(category), c)
        label1.move(50, 20)
        label1.show()
        categoryListWidget = QListWidget(c)
        optionSet = set()
        for key in self.climateData:
            optionSet.add(self.climateData[key][category])
        for option in sorted(list(optionSet)):
            item = QListWidgetItem(option)
            item.setData(Qt.UserRole, option)
            categoryListWidget.addItem(item)
        categoryListWidget.move(50, 50)
        categoryListWidget.resize(200, 400)
        categoryListWidget.show()
        categoryListWidget.clicked.connect(lambda: self.categoryItem_clicked(\
            category, categoryListWidget.currentItem().data(Qt.UserRole)))

        # List showing all datasets associated with the selected option
        label2 = QLabel("Available Datasets:", c)
        label2.move(250, 20)
        label2.show()
        self.datasetListWidget = QListWidget(c)
        self.datasetListWidget.move(250, 50)
        self.datasetListWidget.resize(400, 400)
        self.datasetListWidget.show()

        c.move(QtGui.QApplication.desktop().screen().rect().center() - \
            c.rect().center())
        c.show()

    def categoryItem_clicked(self, category, option):
        self.datasetListWidget.clear()
        results = []
        for key in self.climateData:
            if self.climateData[key][category] == option:
                results.append(self.climateData[key])
        for result in sorted(results):
            item = QListWidgetItem(result["name"])
            item.setData(Qt.UserRole,result)
            self.datasetListWidget.addItem(item)
        self.datasetListWidget.clicked.connect(lambda: self.dataset_clicked(\
            self.datasetListWidget.currentItem().data(Qt.UserRole)));


    def dataset_clicked(self, data):
        # Initiate Table
        keyOrder = ["name", "agency", "instrument", "pvar", "var", "units", "grid", \
        "webvar", "input", "start", "end"]
        sortedData = sorted(data.items(), key=lambda dataPair:keyOrder.index(dataPair[0]))
        self.topServiceTable = QTableWidget()
        t = self.topServiceTable
        t.setWindowTitle(data["name"])
        t.resize(550, 400)
        t.setRowCount(len(data.keys()))
        t.setColumnCount(2)
        t.setColumnWidth(0, 100);
        t.setColumnWidth(1, 400);

        # Set label
        t.setHorizontalHeaderLabels(("Variable;Value").split(";"))

        # Set data
        for row, pair in enumerate(sortedData):
            t.setItem(row, 0, QTableWidgetItem(pair[0]))
            t.setItem(row, 1, QTableWidgetItem(pair[1]))

        t.move(QtGui.QApplication.desktop().screen().rect().topRight() - t.rect().topRight())
        t.show()


    def table_clicked(self):
        """
        Click the table, the graph form may change according to the selection.
        """
        model = self.table.selectionModel()
        indexes = model.selectedIndexes()
        for index in indexes:
            row = index.row()
            #            data = index.model().headerData(0,Qt.Horizontal).toString()
            data = index.model().headerData(0,Qt.Horizontal)
            newIndex = index.model().index(row, 0)
            if data == "API":
                api_id = get_api_full_name(newIndex.model().data(newIndex))
                api = self.data_source.api_by_id(api_id)
                print api
                mashups = self.data_source.mashups_by_api(api)
                apis = []
                for mashup in mashups:
                    apis.extend(self.data_source.apis_by_mashup(mashup))
                self.graph_form.draw_apis(apis, api, self.highlighted_api)
            else:
                mashup_id = get_mashup_full_name(newIndex.model().data(newIndex))
                mashup = self.data_source.mashup_by_id(mashup_id)
                if not mashup:
                    return
                apis = self.data_source.apis_by_mashup(mashup)
                mashups = []
                if len(apis) > 0:
                    mashups.extend(self.data_source.mashups_by_api(apis[0]))
                self.graph_form.draw_mashups(mashups, mashup, self.highlighted_mashup)
            return


    def _show_apis(self, apis, recommend=False):
        self.switch_btn_apis.hide()
        self.switch_btn_mashups.hide()
        self.recommendLabel.hide()

        row = 0
        model = QStandardItemModel(len(apis), 4)
        model.setColumnCount(4)
        #QVariant(...) -> ...
        for api in apis:
            model.setData(model.index(row, 0), get_api_name(api))
            model.setData(model.index(row, 1), api['protocols'])
            model.setData(model.index(row, 2), api['provider'])
            model.setData(model.index(row, 3), api['version'])
            row += 1

        model.setHeaderData(0, Qt.Horizontal, "Service") # Replaced "Module" with "Service"
        model.setHeaderData(1, Qt.Horizontal, "Protocol")
        model.setHeaderData(2, Qt.Horizontal, "Provider")
        model.setHeaderData(3, Qt.Horizontal, "Version")

        self.table.setModel(model)
        self.table.resizeColumnsToContents()
        
        if recommend:
            self.recommendLabel.show()
        
        self.add_btn.show()

    def _show_mashups(self, mashups):
        self.switch_btn_apis.hide()
        self.switch_btn_mashups.hide()
        self.recommendLabel.hide()
        row = 0
        model = QStandardItemModel(len(mashups), 4)
        model.setColumnCount(4)
        for mashup in mashups:
            model.setData(model.index(row, 0), get_mashup_name(mashup))
            model.setData(model.index(row, 1), mashup['title'])
            model.setData(model.index(row, 2), mashup['self'])
            model.setData(model.index(row, 3), mashup['description'])
            
            row += 1
        
        model.setHeaderData(0, Qt.Horizontal, "Workflow")
        model.setHeaderData(1, Qt.Horizontal, "Short Description")
        model.setHeaderData(2, Qt.Horizontal, "Provider")
        model.setHeaderData(3, Qt.Horizontal, "Detailed Info")

        self.table.setModel(model)
        self.table.resizeColumnsToContents()
        self.add_btn.show()

    def api_button_clicked(self):
        """
        Trigger to search APIs
        """        
        self.graph_form.draw_api()
        self.graph_form.show()

        # Get user input from textbox
        apis = self.data_source.apis()
        key = str(self.textbox.toPlainText())
        if key:
            self.api_search_button_clicked()
        else:
            self._show_apis(apis)

    def mashups_button_clicked(self):
        """
        Trigger to search mashups
        """
        self.graph_form.draw_mashup()
        self.graph_form.show()

        key = str(self.textbox.toPlainText())
        print key
        print "button clicked"
        if key:
            self.mashup_search_button_clicked()
        else:
            self._show_mashups(self.data_source.mashups())

    #Should probably refactor this into one method.
    def api_search_button_clicked(self):
        """
        Search when keyword is present
        """
        self.highlighted_api = None
        self.highlighted_mashup = None
        key = str(self.textbox.toPlainText())
        if key != "":
            apis = self.data_source.search_api(key)
            self._show_apis(apis)

    def mashup_search_button_clicked(self):
        """
        Search when keyword is present
        """
        self.highlighted_api = None
        self.highlighted_mashup = None
        key = str(self.textbox.toPlainText())
        if key != "":
            mashups = self.data_source.search_mashup(key)
            self._show_mashups(mashups)
    
    def add_new_api(self):
        """
        Add new api to the modules package.
        """
        apis = self.data_source.apis()
        model = self.table.selectionModel()
        indexes = model.selectedIndexes()
        for index in indexes:
            api = apis[index.row()]
            self._add_new_api(api)
            return
    
    def add_related_api(self):
        objs = []
        for mashup in self.related_mashups:
            objs.append(mashup)
            for api in mashup["related_mashups"]:
                objs.append(api)
        model = self.table.selectionModel()
        indexes = model.selectedIndexes()
        for index in indexes:
            api = objs[index.row()]
            if api.get("protocols"):
                self._add_new_api(api)
                return

    def _show_related_mashups(self):
        self.switch_btn_apis.hide()
        self.switch_btn_mashups.hide()
        self.recommendLabel.hide()
        
        apis = []
        objs = []
        for mashup in self.related_mashups:
            apis.extend(mashup["related_mashups"])

        for api in apis:
            objs.append(api)
            mashups = self.data_source.mashups_by_api(api)
            objs.extend(mashups)

        row = 0
        model = QStandardItemModel(len(objs), 4)
        model.setColumnCount(4)
        for obj in objs:
            if obj.get('protocols'):
                model.setData(model.index(row, 0), get_api_name(obj))
                model.setData(model.index(row, 1), obj['protocols'])
                model.setData(model.index(row, 2), obj['provider'])
            else:
                model.setData(model.index(row, 3), get_mashup_name(obj))
            row += 1

        model.setHeaderData(0, Qt.Horizontal, "API")
        model.setHeaderData(1, Qt.Horizontal, "Protocols")
        model.setHeaderData(2, Qt.Horizontal, "Provider")
        model.setHeaderData(3, Qt.Horizontal, "Mashup")
        self.table.setModel(model)
        self.table.resizeColumnsToContents()
        self.switch_btn_apis.show()

    def _show_related_apis(self):
        self.switch_btn_apis.hide()
        self.switch_btn_mashups.hide()
        self.recommendLabel.hide()
        
        row = 0
        objs = []
        for mashup in self.related_mashups:
            objs.append(mashup)
            for api in mashup["related_mashups"]:
                objs.append(api)
        #Combining similarity and related.
        similar_apis = self.data_source.search_api_similarity(self.highlighted_api)
        #return str(mashup['id'])[(len("http://www.programmableweb.com/mashup/")):]
        objs.append({'id': "http://www.programmableweb.com/mashup/Using-Similarity-Metric"})
        objs.extend(similar_apis)
        #Combining similarity and related.

        #http://localhost:9000/getReputation/John%20Lions
        model = QStandardItemModel(len(objs), 6)
        for obj in objs:
            if obj.get('protocols'):
                model.setData(model.index(row, 1), get_api_name(obj))
                model.setData(model.index(row, 2), obj['protocols'])
                model.setData(model.index(row, 3), obj['provider'])
                model.setData(model.index(row, 4), obj['version'])
                #trust  = requests.get('http://localhost:9000/getReputation/Luis Ramos').content
                model.setData(model.index(row, 5), str(random.random()))
                #model.setData(model.index(row, 5), QVariant(trust))
            else:
                model.setData(model.index(row, 0), get_mashup_name(obj))
            row += 1

        model.setHeaderData(0, Qt.Horizontal, "Mashup")
        model.setHeaderData(1, Qt.Horizontal, "API")
        model.setHeaderData(2, Qt.Horizontal, "Protocols")
        model.setHeaderData(3, Qt.Horizontal, "Provider")
        model.setHeaderData(4, Qt.Horizontal, "Version")
        model.setHeaderData(5, Qt.Horizontal, "Trust")

        self.table.setModel(model)
        self.table.resizeColumnsToContents()
        self.switch_btn_mashups.show()

    def _add_new_api(self, api):
        self.highlighted_api = api
        mashups = self.data_source.mashups_by_api(api)
        for mashup in mashups:
            mashup['related_mashups'] = (self.data_source.apis_by_mashup(mashup))
        if len(mashups) > 0:
            self.related_mashups = mashups
            self._show_related_apis()
        manager = core.packagemanager.get_package_manager()
        reg = core.modules.module_registry.get_module_registry()
        package = manager.get_package("edu.cmu.sv.components", "1.0.0")
        core.modules.module_registry.set_current_package(package)

        if (api["protocols"] == "SOAP" and api["wsdl"] != ""):
            s = Service(api["wsdl"])
#            add_new_service(s, api["wsdl"])
        else:
            new_module = vistrails_module.new_module(Module, get_api_name(api))
            reg.add_module(new_module)
    
            reg.add_input_port(new_module, "value1",
                         (core.modules.basic_modules.String, 'the first argument'))
            reg.add_input_port(new_module, "value2",
                         (core.modules.basic_modules.String, 'the second argument'))
            reg.add_output_port(new_module, "value",
                          (core.modules.basic_modules.String, 'the result'))

    # def loadClimateDataSet(self):
    #     filename = '/home/hywel/Documents/VisTrailsRecommendation/vistrails_current/vistrails/packages/componentSearch/Climate_Datasets.csv'
    #     with open(filename, mode='r') as infile:
    #         reader = csv.reader(infile)
    #         next(reader, None)
    #         with open('coors_new.csv', mode='w') as outfile:
    #             writer = csv.writer(outfile)
    #             climateData = {}
    #             for row in reader:
    #                 id = int(row[0])
    #                 climateData[id] = {}
    #                 climateData[id]["dataset"] = row[1]
    #                 climateData[id]["agency"] = row[2]
    #                 climateData[id]["instrument"] = row[3]
    #                 climateData[id]["pvar"] = row[4]
    #                 climateData[id]["var"] = row[5]
    #                 climateData[id]["units"] = row[6]
    #                 climateData[id]["grid"] = row[7]
    #                 climateData[id]["webvar"] = row[8]
    #                 climateData[id]["input"] = row[9]
    #                 climateData[id]["start"] = row[10]
    #                 climateData[id]["end"] = row[11]
    #     return climateData

    def parseServerData(self, data):
        climateData = {}
        for dataset in data:
            id = int(dataset["datasetID"])
            climateData[id] = {}
            climateData[id]["name"] = dataset["dataset"]
            climateData[id]["agency"] = dataset["agency"]
            climateData[id]["instrument"] = dataset["instrument"]
            climateData[id]["pvar"] = dataset["pvar"]
            climateData[id]["var"] = dataset["var"]
            climateData[id]["units"] = dataset["units"]
            climateData[id]["grid"] = dataset["grid"]
            climateData[id]["webvar"] = dataset["webvar"]
            climateData[id]["input"] = dataset["input"]
            climateData[id]["start"] = dataset["start"]
            climateData[id]["end"] = dataset["end"]
        return climateData
Пример #17
0
class QueueDialog(Window):
    def __init__(self, base):
        Window.__init__(self, base, i18n.get('messages_queue'))
        self.setFixedSize(500, 400)
        self.last_timestamp = None
        self.showed = False

        self.list_ = QTableView()
        self.list_.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.list_.clicked.connect(self.__account_clicked)

        self.caption = QLabel()
        self.caption.setWordWrap(True)
        self.caption.setAlignment(Qt.AlignCenter)

        self.estimated_time = QLabel()
        self.estimated_time.setWordWrap(True)
        self.estimated_time.setAlignment(Qt.AlignCenter)

        self.delete_button = QPushButton(i18n.get('delete'))
        self.delete_button.setEnabled(False)
        self.delete_button.setToolTip(i18n.get('delete_selected_message'))
        self.delete_button.clicked.connect(self.__delete_message)

        self.clear_button = QPushButton(i18n.get('delete_all'))
        self.clear_button.setEnabled(False)
        self.clear_button.setToolTip(i18n.get('delete_all_messages_in_queue'))
        self.clear_button.clicked.connect(self.__delete_all)

        button_box = QHBoxLayout()
        button_box.addStretch(1)
        button_box.addWidget(self.clear_button)
        button_box.addWidget(self.delete_button)

        layout = QVBoxLayout()
        layout.addWidget(self.list_, 1)
        layout.addWidget(self.caption)
        layout.addWidget(self.estimated_time)
        layout.addLayout(button_box)
        layout.setSpacing(5)
        layout.setContentsMargins(5, 5, 5, 5)
        self.setLayout(layout)

    def __account_clicked(self, point):
        self.delete_button.setEnabled(True)
        self.clear_button.setEnabled(True)

    def __delete_message(self):
        self.__disable()
        selection = self.list_.selectionModel()
        index = selection.selectedIndexes()[0]
        message = i18n.get('delete_message_from_queue_confirm')
        confirmation = self.base.show_confirmation_message(i18n.get('confirm_delete'),
            message)
        if not confirmation:
            self.__enable()
            return
        self.base.delete_message_from_queue(index.row())

    def __delete_all(self):
        self.__disable()
        message = i18n.get('clear_message_queue_confirm')
        confirmation = self.base.show_confirmation_message(i18n.get('confirm_delete'),
            message)
        if not confirmation:
            self.__enable()
            return
        self.base.clear_queue()


    def __enable(self):
        self.list_.setEnabled(True)
        self.delete_button.setEnabled(False)
        if len(self.base.core.list_statuses_queue()) > 0:
            self.clear_button.setEnabled(True)
        else:
            self.clear_button.setEnabled(False)

    def __disable(self):
        self.list_.setEnabled(False)
        self.delete_button.setEnabled(False)
        self.clear_button.setEnabled(False)

    def __on_timeout(self):
        now = int(time.time())
        interval = self.base.core.get_queue_interval() * 60
        if self.last_timestamp:
            est_time = ((self.last_timestamp + interval) - now) / 60
        else:
            est_time = 0

        humanized_est_time = self.base.humanize_time_intervals(est_time)
        next_message = ' '.join([i18n.get('next_message_should_be_posted_in'), humanized_est_time])

        if len(self.base.core.list_statuses_queue()) == 0:
            self.estimated_time.setText('')
        else:
            self.estimated_time.setText(next_message)

    def start(self):
        self.timer = QTimer()
        self.timer.timeout.connect(self.__on_timeout)
        self.timer.start(60000)

    def closeEvent(self, event=None):
        if event:
            event.ignore()
        self.hide()
        self.showed = False

    def show(self):
        if self.showed:
            self.raise_()
            return

        self.update()
        Window.show(self)
        self.showed = True

    def update(self):
        model = QStandardItemModel()
        model.setHorizontalHeaderItem(0, QStandardItem(i18n.get('account')))
        model.setHorizontalHeaderItem(1, QStandardItem(i18n.get('message')))
        self.list_.setModel(model)

        now = int(time.time())
        interval = self.base.core.get_queue_interval() * 60
        if self.last_timestamp:
            est_time = ((self.last_timestamp + interval) - now) / 60
        else:
            est_time = 0

        row = 0
        for status in self.base.core.list_statuses_queue():
            username = get_username_from(status.account_id)
            protocol_image = "%s.png" % get_protocol_from(status.account_id)
            item = QStandardItem(QString.fromUtf8(username))
            item.setIcon(QIcon(self.base.load_image(protocol_image, True)))
            model.setItem(row, 0, item)
            model.setItem(row, 1, QStandardItem(QString.fromUtf8(status.text)))
            row += 1

        humanized_interval = self.base.humanize_time_intervals(self.base.core.get_queue_interval())
        humanized_est_time = self.base.humanize_time_intervals(est_time)

        warning = i18n.get('messages_will_be_send') % humanized_interval
        next_message = ' '.join([i18n.get('next_message_should_be_posted_in'), humanized_est_time])
        self.caption.setText(warning)

        if row == 0:
            self.estimated_time.setText('')
        else:
            self.estimated_time.setText(next_message)

        self.list_.horizontalHeader().setResizeMode(1, QHeaderView.Stretch)
        self.list_.resizeColumnsToContents()

        self.__enable()

    def update_timestamp(self):
        if len(self.base.core.list_statuses_queue()) > 0:
            self.last_timestamp = int(time.time())
        else:
            self.last_timestamp = None
class LayerSelectionPage(QFrame):
    #TODO. Filtering, (visible) row selection, multi selection
    colparams = ((0, 65, 'Name'), (1, 235, 'Title'), (2, 350, 'Keywords'))
    XFER_BW = 40

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

        #convenience link
        self.confconn_link = self.parent.parent.confconn

        #flag top prevent read read action on keyword delete. New logic makes this redundant
        #self.keywordbypass = False

        QToolTip.setFont(QFont('SansSerif', 10))

        #label
        filterlabel = QLabel('Filter')
        availablelabel = QLabel('Available Layers')
        selectionlabel = QLabel('Layer Selections')
        keywordlabel = QLabel('Keyword')
        explainlabel = QLabel(
            "Edit Group assignments using this dialog or to simply initialise the Layer-Config just click 'Finish'"
        )

        #selection buttons
        chooseallbutton = QPushButton('>>')
        chooseallbutton.setFixedWidth(self.XFER_BW)
        chooseallbutton.clicked.connect(self.doChooseAllClickAction)

        choosebutton = QPushButton('>')
        choosebutton.setFixedWidth(self.XFER_BW)
        choosebutton.clicked.connect(self.doChooseClickAction)

        rejectbutton = QPushButton('<')
        rejectbutton.setFixedWidth(self.XFER_BW)
        rejectbutton.clicked.connect(self.doRejectClickAction)

        rejectallbutton = QPushButton('<<')
        rejectallbutton.setFixedWidth(self.XFER_BW)
        rejectallbutton.clicked.connect(self.doRejectAllClickAction)

        #operation buttons
        finishbutton = QPushButton('Finish')
        finishbutton.setToolTip('Finish and Close layer selection dialog')
        finishbutton.clicked.connect(self.parent.close)

        resetbutton = QPushButton('Reset')
        resetbutton.font()
        resetbutton.setToolTip(
            'Read Layer from LDS GetCapabilities request. Overwrites current Layer Config'
        )
        resetbutton.clicked.connect(self.doResetClickAction)

        self.available_sfpm = LDSSFPAvailableModel(self)
        self.selection_sfpm = LDSSFPSelectionModel(self)

        self.available_sfpm.setSourceModel(self.parent.available_model)
        self.selection_sfpm.setSourceModel(self.parent.selection_model)

        #textedits
        filteredit = QLineEdit('')
        filteredit.setToolTip(
            'Filter Available-Layers pane (filter operates across Name and Title fields and accepts Regex expressions)'
        )
        filteredit.textChanged.connect(self.available_sfpm.setActiveFilter)

        self.keywordcombo = QComboBox()
        self.keywordcombo.setToolTip(
            'Select or Add a unique identifier to be saved in layer config (keyword)'
        )
        self.keywordcombo.addItems(list(self.confconn_link.assigned))
        self.keywordcombo.setEditable(True)
        self.keywordcombo.activated.connect(self.doKeyComboChangeAction)

        lgindex = self.confconn_link.getLayerGroupIndex(
            self.confconn_link.lgval, col=1)
        lgentry = self.confconn_link.lglist[lgindex] if LU.assessNone(
            lgindex) else None
        #keywordedit = self.keywordcombo.lineEdit().text().toUtf8().data().decode('utf8')# for writing
        #if no entry or layer indicated then blank
        self.keywordcombo.lineEdit().setText(
            '' if lgentry is None or lgentry[0] == LORG.LAYER else
            lgentry[1])  #self.confconn_link.lgval)#TODO. group only

        #header
        headmodel = QStandardItemModel()
        headmodel.setHorizontalHeaderLabels([
            i[2] for i in self.colparams
        ][:self.parent.available_model.columnCount()])

        headview1 = QHeaderView(Qt.Horizontal)
        headview1.setModel(headmodel)
        headview1.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)

        headview2 = QHeaderView(Qt.Horizontal)
        headview2.setModel(headmodel)
        headview2.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)

        #table
        self.available = QTableView()
        self.available.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.available.setSelectionMode(QAbstractItemView.MultiSelection)

        self.selection = QTableView()
        self.selection.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.selection.setSelectionMode(QAbstractItemView.MultiSelection)

        #interesting, must set model after selection attributes but before headers else row selections/headers don't work properly
        self.available.setModel(self.available_sfpm)
        self.selection.setModel(self.selection_sfpm)

        self.available.setSortingEnabled(True)
        self.available.setHorizontalHeader(headview1)

        self.selection.setSortingEnabled(True)
        self.selection.setHorizontalHeader(headview2)

        for cp in self.colparams:
            self.available.setColumnWidth(cp[0], cp[1])
            self.selection.setColumnWidth(cp[0], cp[1])

        self.available.verticalHeader().setVisible(False)
        self.available.horizontalHeader().setVisible(True)

        self.selection.verticalHeader().setVisible(False)
        self.selection.horizontalHeader().setVisible(True)

        #layout
        vbox00 = QVBoxLayout()
        vbox00.addWidget(availablelabel)
        vbox00.addWidget(self.available)

        vbox01 = QVBoxLayout()
        vbox01.addWidget(chooseallbutton)
        vbox01.addWidget(choosebutton)
        vbox01.addWidget(rejectbutton)
        vbox01.addWidget(rejectallbutton)

        vbox02 = QVBoxLayout()
        vbox02.addWidget(selectionlabel)
        vbox02.addWidget(self.selection)

        vbox10 = QVBoxLayout()
        vbox10.addWidget(filterlabel)
        vbox10.addWidget(filteredit)

        hbox12 = QHBoxLayout()
        hbox12.addWidget(keywordlabel)
        hbox12.addStretch(1)
        #hbox12.addWidget(inspbutton)
        #hbox12.addWidget(addbutton)
        #hbox12.addWidget(delbutton)

        vbox12 = QVBoxLayout()
        vbox12.addLayout(hbox12)
        vbox12.addWidget(self.keywordcombo)

        #00|01|02
        #10|11|12
        grid0 = QGridLayout()
        grid0.addLayout(vbox00, 1, 0)
        grid0.addLayout(vbox01, 1, 1)
        grid0.addLayout(vbox02, 1, 2)
        grid0.addLayout(vbox10, 0, 0)
        grid0.addLayout(vbox12, 0, 2)

        hbox2 = QHBoxLayout()
        hbox2.addWidget(resetbutton)
        hbox2.addStretch(1)
        hbox2.addWidget(explainlabel)
        hbox2.addWidget(finishbutton)
        #gbox1.setLayout(hbox2)

        vbox3 = QVBoxLayout()
        vbox3.addLayout(grid0)
        #vbox3.addLayout(hbox3)
        #vbox3.addWidget(line0)
        vbox3.addLayout(hbox2)

        self.setLayout(vbox3)

    def doChooseAllClickAction(self):
        '''Moves the lot to Selected'''
        #ktext = LU.recode(self.keywordcombo.lineEdit().text().toUtf8().data())
        ktext = LU.recode(
            LQ.readWidgetText(self.keywordcombo.lineEdit().text()))
        if not self.checkKeyword(ktext): return
        #------------------------------
        self.parent.signalModels(self.parent.STEP.PRE)
        #self.parent.selection_model.mdata += self.parent.available_model.mdata
        self.parent.selection_model.initData(self.confconn_link.complete)
        self.parent.available_model.initData([])
        self.parent.signalModels(self.parent.STEP.POST)
        #------------------------------
        self.parent.writeKeysToLayerConfig(ktext)
        #self.confconn_link.setupAssignedLayerList()
        if self.keywordcombo.findText(ktext) == -1:
            self.keywordcombo.addItem(ktext)

    def doChooseClickAction(self):
        '''Takes available selected and moves to selection'''
        #ktext = LU.recode(self.keywordcombo.lineEdit().text().toUtf8().data())
        ktext = LU.recode(
            LQ.readWidgetText(self.keywordcombo.lineEdit().text()))
        #ktext = str(self.keywordcombo.lineEdit().text())
        if not self.checkKeyword(ktext): return
        #------------------------------
        select = self.available.selectionModel()
        if select.hasSelection():
            self.transferSelectedRows(select.selectedRows(),
                                      self.available_sfpm, self.selection_sfpm)
            #------------------------------
            self.parent.writeKeysToLayerConfig(ktext)
            #self.confconn_link.assigned = self.confconn_link.setupAssignedLayerList()
            # -1 to indicate no index since 0,1,... are valid
            if self.keywordcombo.findText(ktext) == -1:
                self.keywordcombo.addItem(ktext)
        else:
            ldslog.warn('L2R > Transfer action without selection')
        #TRACE#
        #pdb.set_trace()
        self.available.clearSelection()

    def transferSelectedRows(self, indices, from_model, to_model):
        tlist = []
        for proxymodelindex in indices:
            transfer = from_model.getData(proxymodelindex)
            tlist.append((proxymodelindex, transfer), )

        to_model.addData([t[1] for t in tlist])
        from_model.delData([t[0] for t in tlist])
        return tlist

    def doRejectClickAction(self):
        '''Takes available selected and moves to selection'''
        #ktext = LU.recode(self.keywordcombo.lineEdit().text().toUtf8().data())
        ktext = LU.recode(
            LQ.readWidgetText(self.keywordcombo.lineEdit().text()))
        if not self.checkKeyword(ktext): return
        #------------------------------
        select = self.selection.selectionModel()
        if select.hasSelection():
            tlist = self.transferSelectedRows(select.selectedRows(),
                                              self.selection_sfpm,
                                              self.available_sfpm)
            #------------------------------
            kindex = self.keywordcombo.findText(ktext)
            remainder = self.parent.deleteKeysFromLayerConfig(
                [ll[1][0] for ll in tlist], ktext)
            if remainder > 0 and kindex == -1:
                #items+newkey -> add
                self.parent.writeKeysToLayerConfig(ktext)
                self.keywordcombo.addItem(ktext)
            elif remainder == 0 and kindex > -1:
                #empty+oldkey -> del
                self.keywordcombo.removeItem(kindex)
                self.keywordcombo.clearEditText()
        else:
            ldslog.warn('R2L < Transfer action without selection')
        #TRACE#
        #pdb.set_trace()
        self.selection.clearSelection()

    def doRejectAllClickAction(self):
        #ktext = LU.recode(self.keywordcombo.lineEdit().text().toUtf8().data())
        ktext = LU.recode(
            LQ.readWidgetText(self.keywordcombo.lineEdit().text()))
        if not self.checkKeyword(ktext): return
        #------------------------------
        self.parent.deleteKeysFromLayerConfig(
            [ll[0] for ll in self.parent.selection_model.mdata], ktext)
        #------------------------------
        self.parent.signalModels(self.parent.STEP.PRE)
        #self.parent.available_model.mdata += self.parent.selection_model.mdata
        self.parent.available_model.initData(self.confconn_link.complete)
        self.parent.selection_model.initData([])
        self.parent.signalModels(self.parent.STEP.POST)
        #------------------------------
        #self.confconn_link.setupAssignedLayerList()
        #self.keywordbypass = True
        self.keywordcombo.removeItem(self.keywordcombo.findText(ktext))
        self.keywordcombo.clearEditText()

    def doKeyComboChangeAction(self):
        '''Reset the available pane and if there is anything in the keyword box use this to init the selection pane'''
        #HACK
        #if self.keywordbypass:
        #    self.keywordbypass = False
        #    return
        #------------------------------
        #ktext = LU.recode(self.keywordcombo.lineEdit().text().toUtf8().data())
        ktext = LU.recode(
            LQ.readWidgetText(self.keywordcombo.lineEdit().text()))
        #------------------------------
        av_sl = self.parent.splitData(ktext, self.confconn_link.complete)
        #av_sl = self.parent.splitData(ktext,self.confconn_link.complete)
        self.parent.signalModels(self.parent.STEP.PRE)
        self.parent.available_model.initData(av_sl[0])
        self.parent.selection_model.initData(av_sl[1])
        self.parent.signalModels(self.parent.STEP.POST)

    def doResetClickAction(self):
        '''Dumps the LC and rebuilds from a fresh read of the caps doc'''
        #int warning (QWidget parent, QString title, QString text, QString button0Text, QString button1Text = QString(), QString button2Text = QString(), int defaultButtonNumber = 0, int escapeButtonNumber = -1)
        ans = QMessageBox.warning(
            self, "Reset",
            "This action will overwrite your Layer Configuration using the current LDS settings (potentially adding new or removing layers). Continue?",
            "Continue", "Cancel")
        if ans:
            #Cancel
            ldslog.warn('Cancelling Reset operation')
            return
        #Continue
        ldslog.warn('Reset Layer Config')
        self.parent.resetLayers()
        self.keywordcombo.clear()

    def checkKeyword(self, ktext):
        '''Checks keyword isn't null and isn't part of the LDS supplied keywords'''
        if LU.assessNone(ktext) is None:
            QMessageBox.about(self, "Keyword Required",
                              "Please enter a Keyword to assign Layer(s) to")
            return False
        if ktext in self.confconn_link.reserved:
            QMessageBox.about(
                self, "Reserved Keyword",
                "'{}' is a reserved keyword, please select again".format(
                    ktext))
            return False
        return True
Пример #19
0
    class VizRank(OWWidget):
        name = "Rank projections (Scatter Plot)"

        def __init__(self, parent_widget):
            super().__init__()
            self.parent_widget = parent_widget
            self.want_control_area = False
            self.running = False
            self.progress = None
            self.k = 10

            self.projectionTable = QTableView()
            self.mainArea.layout().addWidget(self.projectionTable)
            self.projectionTable.setSelectionBehavior(QTableView.SelectRows)
            self.projectionTable.setSelectionMode(QTableView.SingleSelection)
            self.projectionTable.setSortingEnabled(True)
            self.projectionTableModel = QStandardItemModel(self)
            self.projectionTable.setModel(self.projectionTableModel)
            self.projectionTable.selectionModel().selectionChanged.connect(
                self.on_selection_changed)

            self.button = gui.button(self.mainArea, self, "Start evaluation",
                                     callback=self.toggle, default=True)
            self.resize(380, 512)
            self._initialize()

        def _initialize(self):
            self.running = False
            self.projectionTableModel.clear()
            self.projectionTableModel.setHorizontalHeaderLabels(
                ["Score", "Feature 1", "Feature 2"])
            self.projectionTable.setColumnWidth(0, 60)
            self.projectionTable.setColumnWidth(1, 120)
            self.projectionTable.setColumnWidth(2, 120)
            self.button.setText("Start evaluation")
            self.button.setEnabled(False)
            self.pause = False
            self.data = None
            self.attrs = []
            self.scores = []
            self.i, self.j = 0, 0
            if self.progress:
                self.progress.finish()
            self.progress = None


            self.information(0)
            if self.parent_widget.data:
                if not self.parent_widget.data.domain.class_var:
                    self.information(
                        0, "Data with a class variable is required.")
                    return
                if len(self.parent_widget.data.domain.attributes) < 2:
                    self.information(
                        0, 'At least 2 unique features are needed.')
                    return
                self.button.setEnabled(True)

        def on_selection_changed(self, selected, deselected):
            """Called when the ranks view selection changes."""
            a1 = selected.indexes()[1].data()
            a2 = selected.indexes()[2].data()
            self.parent_widget.update_attr(attributes=(a1, a2))

        def toggle(self):
            self.running ^= 1
            if self.running:
                self.button.setText("Pause")
                self.run()
            else:
                self.button.setText("Continue")
                self.button.setEnabled(False)

        def run(self):
            graph = self.parent_widget.graph
            y_full = self.parent_widget.data.Y
            norm = 1 / (len(y_full) * self.k)
            if not self.attrs:
                self.attrs = self.score_heuristic()
            if not self.progress:
                self.progress = gui.ProgressBar(
                    self, len(self.attrs) * (len(self.attrs) - 1) / 2)
            for i in range(self.i, len(self.attrs)):
                ind1 = graph.attribute_name_index[self.attrs[i]]
                for j in range(self.j, i):
                    if not self.running:
                        self.i, self.j = i, j
                        if not self.projectionTable.selectedIndexes():
                            self.projectionTable.selectRow(0)
                        self.button.setEnabled(True)
                        return
                    ind2 = graph.attribute_name_index[self.attrs[j]]
                    X = graph.scaled_data[[ind1, ind2], :]
                    valid = graph.get_valid_list([ind1, ind2])
                    X = X[:, valid].T
                    y = y_full[valid]
                    knn = NearestNeighbors(n_neighbors=self.k).fit(X)
                    ind = knn.kneighbors(return_distance=False)
                    score = norm * np.sum(y[ind] == y.reshape(-1, 1))
                    pos = bisect_left(self.scores, score)
                    self.projectionTableModel.insertRow(
                        len(self.scores) - pos,
                        [QStandardItem("{:.4f}".format(score)),
                         QStandardItem(self.attrs[j]),
                         QStandardItem(self.attrs[i])])
                    self.scores.insert(pos, score)
                    self.progress.advance()
                self.j = 0
            self.progress.finish()
            if not self.projectionTable.selectedIndexes():
                self.projectionTable.selectRow(0)
            self.button.setText("Finished")
            self.button.setEnabled(False)

        def score_heuristic(self):
            X = self.parent_widget.graph.scaled_data.T
            Y = self.parent_widget.data.Y
            dom = Orange.data.Domain([ContinuousVariable(str(i))
                                      for i in range(X.shape[1])],
                                     self.parent_widget.data.domain.class_vars)
            data = Orange.data.Table(dom, X, Y)
            weights = ReliefF(n_iterations=100, k_nearest=self.k)(data)
            attrs = sorted(
                zip(weights,
                    (x.name for x in self.parent_widget.data.domain.attributes)
                    ),
                reverse=True)
            return [a for _, a in attrs]
Пример #20
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()))
class ComponentSearchForm():

    data_source = None
    
    related_mashups = None
    
    widget = None
    
    table = None
    
    add_btn = None
    
    graph_form = None
    
    highlighted_api = None
    
    highlighted_mashup = None
    
    def show_main_window(self):
        self.graph_form = matplotlibWidget()
        if self.widget:
            self.widget.destroy()
            self.widget = None;
        self.widget = QWidget()
        self.widget.setMinimumSize(800, 600)
        btn_api = QtGui.QPushButton("Recommend Modules", self.widget)
        btn_api.move(30, 20)

        btn_mashup = QtGui.QPushButton("Recommend Workflows", self.widget)
        btn_mashup.move(200, 20)

        self.textboxLabel = QLabel(self.widget)
        self.textboxLabel.setText("Describe your goals:")
        self.textboxLabel.move(35, 60)
        self.textboxLabel.show
        
        self.textbox = QTextEdit(self.widget)
        self.textbox.move(30, 80)
        self.textbox.setFixedWidth(300)
        self.textbox.setFixedHeight(28)

        btn_api.clicked.connect(self.api_button_clicked)
        btn_mashup.clicked.connect(self.mashups_button_clicked)

        self.table = QTableView(self.widget)
        self.table.clicked.connect(self.table_clicked)
        self.table.setMinimumSize(740, 500)
        self.table.resizeColumnsToContents()
        self.table.move(30, 120)

        self.widget.show()
        
        self.add_btn = QPushButton(self.widget)
        self.add_btn.clicked.connect(self.add_new_api)
        self.add_btn.setText("Add to Palette")
        self.add_btn.hide()
        self.add_btn.move(650, 20)
        
        self.recommendLabel = QLabel(self.widget)
        self.recommendLabel.setText("Also Used")
        self.recommendLabel.move(30, 95)
        self.recommendLabel.hide()
        
        self.switch_btn_apis = QPushButton(self.widget)
        self.switch_btn_apis.clicked.connect(self._show_related_apis)
        self.switch_btn_apis.setText("Related Mashup")
        self.switch_btn_apis.move(500, 20)
        self.switch_btn_apis.hide()
        
        self.switch_btn_mashups = QPushButton(self.widget)
        self.switch_btn_mashups.clicked.connect(self._show_related_mashups)
        self.switch_btn_mashups.setText("Related API")
        self.switch_btn_mashups.move(500, 20)
        self.switch_btn_mashups.hide()

    def __init__(self, parent=None):
        self.data_source = DataSource()
        
    def table_clicked(self):
        """
        Click the table, the graph form may change according to the selection.
        """
        model = self.table.selectionModel()
        indexes = model.selectedIndexes()
        for index in indexes:
            row = index.row()
            data = index.model().headerData(0,Qt.Horizontal).toString()
            newIndex = index.model().index(row, 0)
            if data == "API":
                api_id = get_api_full_name(newIndex.model().data(newIndex).toString())
                api = self.data_source.api_by_id(api_id)
                print api
                mashups = self.data_source.mashups_by_api(api)
                apis = []
                for mashup in mashups:
                    apis.extend(self.data_source.apis_by_mashup(mashup))
                self.graph_form.draw_apis(apis, api, self.highlighted_api)
            else:
                mashup_id = get_mashup_full_name(newIndex.model().data(newIndex).toString())
                mashup = self.data_source.mashup_by_id(mashup_id)
                if not mashup:
                    return
                apis = self.data_source.apis_by_mashup(mashup)
                mashups = []
                if len(apis) > 0:
                    mashups.extend(self.data_source.mashups_by_api(apis[0]))
                self.graph_form.draw_mashups(mashups, mashup, self.highlighted_mashup)
            return


    def _show_apis(self, apis, recommend=False):
        self.switch_btn_apis.hide()
        self.switch_btn_mashups.hide()
        self.recommendLabel.hide()

        row = 0
        model = QStandardItemModel(len(apis), 4)
        model.setColumnCount(4)
        for api in apis:
            model.setData(model.index(row, 0), QVariant(get_api_name(api)))
            model.setData(model.index(row, 1), QVariant(api['protocols']))
            model.setData(model.index(row, 2), QVariant(api['provider']))
            model.setData(model.index(row, 3), QVariant(api['version']))
            row += 1

        model.setHeaderData(0, Qt.Horizontal, QVariant("Module"))
        model.setHeaderData(1, Qt.Horizontal, QVariant("Protocol"))
        model.setHeaderData(2, Qt.Horizontal, QVariant("Provider"))
        model.setHeaderData(3, Qt.Horizontal, QVariant("Version"))

#        model.setHeaderData(0, Qt.Horizontal, QVariant("API"))
#        model.setHeaderData(1, Qt.Horizontal, QVariant("Protocols"))
#        model.setHeaderData(2, Qt.Horizontal, QVariant("Provider"))
#        model.setHeaderData(3, Qt.Horizontal, QVariant("Version"))

        self.table.setModel(model)
        self.table.resizeColumnsToContents()
        
        if recommend:
            self.recommendLabel.show()
        
        self.add_btn.show()

    def _show_mashups(self, mashups):
        self.switch_btn_apis.hide()
        self.switch_btn_mashups.hide()
        self.recommendLabel.hide()

        row = 0
        model = QStandardItemModel(len(mashups), 4)
        model.setColumnCount(4)
        for mashup in mashups:
            model.setData(model.index(row, 0), QVariant(get_mashup_name(mashup)))
            model.setData(model.index(row, 1), QVariant(mashup['title']))
            model.setData(model.index(row, 2), QVariant(mashup['self']))
            model.setData(model.index(row, 3), QVariant(mashup['description']))
            
            row += 1
        
        model.setHeaderData(0, Qt.Horizontal, QVariant("Workflow"))
        model.setHeaderData(1, Qt.Horizontal, QVariant("Short Description"))
        model.setHeaderData(2, Qt.Horizontal, QVariant("Provider"))
        model.setHeaderData(3, Qt.Horizontal, QVariant("Detailed Info"))

#        model.setHeaderData(0, Qt.Horizontal, QVariant("Info"))
#        model.setHeaderData(1, Qt.Horizontal, QVariant("Title"))
#        model.setHeaderData(2, Qt.Horizontal, QVariant("self"))
#        model.setHeaderData(3, Qt.Horizontal, QVariant("Description"))

        self.table.setModel(model)
        self.table.resizeColumnsToContents()
        self.add_btn.show()

    def api_button_clicked(self):
        """
        Trigger to search APIs
        """        
        self.graph_form.draw_api()
        self.graph_form.show()

        apis = self.data_source.apis()
        key = str(self.textbox.toPlainText())
        #Has key or not has key, it is different.
        if key:
            self.api_search_button_clicked()
        else:
            self._show_apis(apis)

    def mashups_button_clicked(self):
        """
        Trigger to search mashups
        """
        self.graph_form.draw_mashup()
        self.graph_form.show()

        key = str(self.textbox.toPlainText())
        if key:
            self.mashup_search_button_clicked()
        else:
            self._show_mashups(self.data_source.mashups())

    #Should probably refactor this into one method.
    def api_search_button_clicked(self):
        """
        Search when no keyword
        """
        self.highlighted_api = None
        self.highlighted_mashup = None
        key = str(self.textbox.toPlainText())
        if key != "":
            apis = self.data_source.search_api(key)
            self._show_apis(apis)

    def mashup_search_button_clicked(self):
        """
        Search when no keyword
        """
        self.highlighted_api = None
        self.highlighted_mashup = None
        key = str(self.textbox.toPlainText())
        if key != "":
            mashups = self.data_source.search_mashup(key)
            self._show_mashups(mashups)
    
    def add_new_api(self):
        """
        Add new api to the modules package.
        """
        apis = self.data_source.apis()
        model = self.table.selectionModel()
        indexes = model.selectedIndexes()
        for index in indexes:
            api = apis[index.row()]
            self._add_new_api(api)
            return
    
    def add_related_api(self):
        objs = []
        for mashup in self.related_mashups:
            objs.append(mashup)
            for api in mashup["related_mashups"]:
                objs.append(api)
        model = self.table.selectionModel()
        indexes = model.selectedIndexes()
        for index in indexes:
            api = objs[index.row()]
            if api.get("protocols"):
                self._add_new_api(api)
                return

    def _show_related_mashups(self):
        self.switch_btn_apis.hide()
        self.switch_btn_mashups.hide()
        self.recommendLabel.hide()
        
        apis = []
        objs = []
        for mashup in self.related_mashups:
            apis.extend(mashup["related_mashups"])

        for api in apis:
            objs.append(api)
            mashups = self.data_source.mashups_by_api(api)
            objs.extend(mashups)

        row = 0
        model = QStandardItemModel(len(objs), 4)
        model.setColumnCount(4)
        for obj in objs:
            if obj.get('protocols'):
                model.setData(model.index(row, 0), QVariant(get_api_name(obj)))
                model.setData(model.index(row, 1), QVariant(obj['protocols']))
                model.setData(model.index(row, 2), QVariant(obj['provider']))
            else:
                model.setData(model.index(row, 3), QVariant(get_mashup_name(obj)))
            row += 1

        model.setHeaderData(0, Qt.Horizontal, QVariant("API"))
        model.setHeaderData(1, Qt.Horizontal, QVariant("Protocols"))
        model.setHeaderData(2, Qt.Horizontal, QVariant("Provider"))
        model.setHeaderData(3, Qt.Horizontal, QVariant("Mashup"))
        self.table.setModel(model)
        self.table.resizeColumnsToContents()
        self.switch_btn_apis.show()

    def _show_related_apis(self):
        self.switch_btn_apis.hide()
        self.switch_btn_mashups.hide()
        self.recommendLabel.hide()
        
        row = 0
        objs = []
        for mashup in self.related_mashups:
            objs.append(mashup)
            for api in mashup["related_mashups"]:
                objs.append(api)
        #Combining similarity and related.
        similar_apis = self.data_source.search_api_similarity(self.highlighted_api)
        #return str(mashup['id'])[(len("http://www.programmableweb.com/mashup/")):]
        objs.append({'id': "http://www.programmableweb.com/mashup/Using-Similarity-Metric"})
        objs.extend(similar_apis)
        #Combining similarity and related.

        model = QStandardItemModel(len(objs), 5)
        for obj in objs:
            if obj.get('protocols'):
                model.setData(model.index(row, 1), QVariant(get_api_name(obj)))
                model.setData(model.index(row, 2), QVariant(obj['protocols']))
                model.setData(model.index(row, 3), QVariant(obj['provider']))
                model.setData(model.index(row, 4), QVariant(obj['version']))
            else:
                model.setData(model.index(row, 0), QVariant(get_mashup_name(obj)))
            row += 1

        model.setHeaderData(0, Qt.Horizontal, QVariant("Mashup"))
        model.setHeaderData(1, Qt.Horizontal, QVariant("API"))
        model.setHeaderData(2, Qt.Horizontal, QVariant("Protocols"))
        model.setHeaderData(3, Qt.Horizontal, QVariant("Provider"))
        model.setHeaderData(4, Qt.Horizontal, QVariant("Version"))

        self.table.setModel(model)
        self.switch_btn_mashups.show()

    def _add_new_api(self, api):
        self.highlighted_api = api
        mashups = self.data_source.mashups_by_api(api)
        for mashup in mashups:
            mashup['related_mashups'] = (self.data_source.apis_by_mashup(mashup))
        if len(mashups) > 0:
            self.related_mashups = mashups
            self._show_related_apis()
        manager = core.packagemanager.get_package_manager()
        reg = core.modules.module_registry.get_module_registry()
        package = manager.get_package("edu.cmu.sv.components", "1.0.0")
        core.modules.module_registry.set_current_package(package)

        if (api["protocols"] == "SOAP" and api["wsdl"] != ""):
            s = Service(api["wsdl"])
            add_new_service(s, api["wsdl"])
        else:
            new_module = vistrails_module.new_module(Module, get_api_name(api))
            reg.add_module(new_module)
    
            reg.add_input_port(new_module, "value1",
                         (core.modules.basic_modules.String, 'the first argument'))
            reg.add_input_port(new_module, "value2",
                         (core.modules.basic_modules.String, 'the second argument'))
            reg.add_output_port(new_module, "value",
                          (core.modules.basic_modules.String, 'the result'))
Пример #22
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)
Пример #23
0
class OWMPR(OWWidget):
    name = 'ModelMap Projection Rank'
    description = 'Ranking projections by estimating projection quality'
    icon = "icons/ModelMap.svg"

    inputs = [('Data', Table, 'set_data', Default)]
    outputs = [('Features', AttributeList)]
    want_main_area = False
    settingsHandler = DomainContextHandler()

    variable_changed = Signal()

    def __init__(self):
        super().__init__()
        self.data = None
        self.progress = None

        self.infoa = gui.widgetLabel(self.controlArea, "No data loaded.")

        self.projectionTable = QTableView()
        self.controlArea.layout().addWidget(self.projectionTable)
        self.projectionTable.setSelectionBehavior(QTableView.SelectRows)
        self.projectionTable.setSelectionMode(QTableView.SingleSelection)
        self.projectionTable.setSortingEnabled(True)

        self.projectionTableModel = QStandardItemModel(self)
        self.projectionTableModel.setHorizontalHeaderLabels(["P-Index", "", ""])
        self.projectionTable.setModel(self.projectionTableModel)

        self.projectionTable.setColumnWidth(0, 90)
        self.projectionTable.sortByColumn(0, Qt.DescendingOrder)
        self.projectionTable.selectionModel().selectionChanged.connect(self.on_selection_changed)

        gui.button(self.controlArea, self, "Rank Projections", callback=self.rank, default=True)
        self.resize(370, 600)

    def set_data(self, data):
        self.data = data
        self.infoa.setText("Data set: {}".format(data.name) if self.data else "No data loaded.")

    def rank(self):
        if self.progress:
            return

        disc = Orange.preprocess.discretize.EqualWidth(n=10)

        ndomain = Orange.data.Domain(
                [disc(self.data, attr) if type(attr) == Orange.data.variable.ContinuousVariable
                 else attr for attr in self.data.domain.attributes], self.data.domain.class_vars)

        t = self.data.from_table(ndomain, self.data)

        attrs = t.domain.attributes

        tables = {}
        l = 0
        self.progress = gui.ProgressBar(self, len(attrs) * (len(attrs) - 1) / 2)
        for i in range(len(attrs)):
            for j in range(i):
                ct = np.array(contingency.get_contingency(t, attrs[j], attrs[i]))
                pindex, _, _ = p_index(ct)
                tables[i, j] = ct

                item = QStandardItem()
                item.setData(float(pindex), Qt.DisplayRole)
                self.projectionTableModel.setItem(l, 0, item)

                item = QStandardItem()
                item.setData(attrs[i].name, Qt.DisplayRole)
                self.projectionTableModel.setItem(l, 1, item)

                item = QStandardItem()
                item.setData(attrs[j].name, Qt.DisplayRole)
                self.projectionTableModel.setItem(l, 2, item)

                self.progress.advance()
                l += 1

        self.progress.finish()
        self.progress = None

    def on_selection_changed(self, selected, deselected):
        """Called when the ranks view selection changes."""
        a1 = selected.indexes()[1].data().replace('D_', '')
        a2 = selected.indexes()[2].data().replace('D_', '')
        d = self.data.domain
        self.send("Features", AttributeList([d[a1], d[a2]]))
Пример #24
0
class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        uic.loadUi("mainwindow.ui", self)

        model = QStandardItemModel(7, 4, self)
        for row in range(7):
            for column in range(4):
                item = QStandardItem(QString("%1").arg(row * 4 + column))
                model.setItem(row, column, item)

        self.tableView = QTableView()
        self.tableView.setModel(model)
        self.setCentralWidget(self.tableView)

        # 获取视图的项目选择模型
        selectionModel = self.tableView.selectionModel()

        # 定义左上角和右下角的索引,然后使用这两个索引创建选择
        topLeft = model.index(1, 1, QModelIndex())
        bottomRight = model.index(5, 2, QModelIndex())
        selection = QItemSelection(topLeft, bottomRight)

        # 使用指定的选择模式来选择项目
        selectionModel.select(selection, QItemSelectionModel.Select)

        self.mainToolBar.addAction(_fromUtf8("当前项目"), self.getCurrentItemData)
        self.mainToolBar.addAction(_fromUtf8("切换选择"), self.toggleSelection)

        self.connect(selectionModel,SIGNAL("selectionChanged(QItemSelection,QItemSelection)"),
                     self.updateSelection)
        self.connect(selectionModel, SIGNAL("currentChanged(QModelIndex,QModelIndex)"),
                self.changeCurrent)

        # 多个视图共享选择
        self.tableView2 = QTableView()
        self.tableView2.setWindowTitle("tableView2")
        self.tableView2.resize(400, 300)
        self.tableView2.setModel(model)
        self.tableView2.setSelectionModel(selectionModel)
        self.tableView2.show()

    # 输出当前项目的内容
    def getCurrentItemData(self, ):

        print  "当前项目的内容:", \
            self.tableView.selectionModel().currentIndex().data().toString()

    # 切换选择的项目
    def toggleSelection(self):
        topLeft = self.tableView.model().index(0, 0, QModelIndex())
        bottomRight = self.tableView.model().index(
            self.tableView.model().rowCount(QModelIndex()) - 1,
            self.tableView.model().columnCount(QModelIndex()) - 1, QModelIndex())
        curSelection = QItemSelection(topLeft, bottomRight)
        self.tableView.selectionModel().select(curSelection, QItemSelectionModel.Toggle)

    # 更新选择
    def updateSelection(self,selected, deselected):

        mlist = selected.indexes()
        # 为现在选择的项目填充值
        for index in mlist:
            text = QString("(%1,%2)").arg(index.row()).arg(index.column())
            self.tableView.model().setData(index, text)

        mlist = deselected.indexes()
        # 清空上一次选择的项目的内容
        for index in mlist:
            self.tableView.model().setData(index, "")

    # 改变当前项目
    def changeCurrent(self, current, previous):

        print  QString("move(%1,%2) to (%3,%4)")\
            .arg(previous.row()).arg(previous.column()) \
            .arg(current.row()).arg(current.column())