示例#1
0
文件: tests.py 项目: eric-downes/Wren
    def test_get(self):
        from app import get_application
        app = get_application()
        app.init_ui()
        self.assertIsNotNone(app)

        from controllers import get
        grid = get('main_grid')
示例#2
0
文件: tests.py 项目: eric-downes/Wren
    def test_evaluator_errors(self):
        from app import get_application
        get_application().init_ui()

        from controllers import BlankClip, get, Text, TextClip
        from model import GridModel
        grid_model = GridModel(key='test_grid')
        grid_model.save()
        grid = get('test_grid')
        self.assertIsNotNone(grid)

        grid.eval_declarations()
        for y in range(2):
            for x in range(5):
                text = Text.create('')

                # This is a hack to avoid some UI stuff during tests.
                clip = TextClip.create(grid.model.key, text.model.key, x, y)
                grid.coordinates_to_clip[(x, y)] = clip
                #grid.add_text(text, x, y)
        grid.eval_declarations()

        # Declare an attribute on all Datums
        cmd = '#*foo:22'
        star_declaration = grid.coordinates_to_clip[(1, 0)]
        star_declaration.datum.model.data = cmd
        star_declaration.datum.model.save()
        grid.eval_declarations()
        self.assertEqual({'foo': '22'}, grid.grid_declarations)
        self.assertEqual({}, grid.declarations_by_clip)

        # Test error handling
        def _check_subcommands(cmd, clip):
            for i in range(len(cmd)):
                subcmd = cmd[:i+1]
                clip.datum.model.data = subcmd
                clip.datum.model.save()
                #log.info('---check subcommand {0}'.format(subcmd))
                grid.eval_declarations()

        clip = grid.coordinates_to_clip[(4, 0)]
        cmd = '#*bar:22'
        _check_subcommands(cmd, clip)
        cmd = '#*bar:22\n#bar+bar'
        _check_subcommands(cmd, clip)

        self.assertEqual({'foo': '22', 'bar': '22'}, grid.grid_declarations)
        self.assertEqual({}, grid.declarations_by_clip)
示例#3
0
文件: tests.py 项目: eric-downes/Wren
    def test_evaluator(self):
        from app import get_application
        get_application().init_ui()

        from controllers import BlankClip, get, Text, TextClip
        from model import GridModel
        grid_model = GridModel(key='test_grid')
        grid_model.save()
        grid = get('test_grid')
        self.assertIsNotNone(grid)

        grid.eval_declarations()
        for y in range(2):
            for x in range(5):
                text = Text.create('')

                # This is a hack to avoid some UI stuff during tests.
                clip = TextClip.create(grid.model.key, text.model.key, x, y)
                grid.coordinates_to_clip[(x, y)] = clip
                # grid.add_text(text, x, y)
        grid.eval_declarations()

        cmd1 = '#*foo:22\n#*bar:foo+&foo'
        cmd2 = '#foo\n#bar\n#foo:42'

        cursor_clip = grid.get_cursor_clip()
        self.assertIsInstance(cursor_clip, BlankClip)
        secondary_cursor_clip = grid.get_secondary_cursor_clip()
        self.assertIsInstance(secondary_cursor_clip, BlankClip)

        cmd1_x = 2
        cmd1_y = 0
        cmd2_x = 4
        cmd2_y = 1
        grid.main_cursor.model.x = cmd2_x
        grid.main_cursor.model.y = cmd2_y
        grid.main_cursor.model.save()
        grid.secondary_cursor.model.x = cmd1_x
        grid.secondary_cursor.model.y = cmd1_y
        grid.secondary_cursor.model.save()

        cmd1_clip = grid.coordinates_to_clip[(cmd1_x, cmd1_y)]
        cmd1_clip.datum.model.data = cmd1
        cmd1_clip.datum.model.save()
        cmd2_clip = grid.coordinates_to_clip[(cmd2_x, cmd2_y)]
        cmd2_clip.datum.model.data = cmd2
        cmd2_clip.datum.model.save()

        self.assertIs(cmd2_clip, grid.get_cursor_clip())
        self.assertIs(cmd1_clip, grid.get_secondary_cursor_clip())

        grid.eval_declarations()
        self.assertEqual({'foo': '22', 'bar': 'foo+&foo'},
                         grid.grid_declarations)
        self.assertEqual({cmd2_clip.datum.model.name: {'foo': '42'}},
                         grid.declarations_by_clip)

        # This simulates what the inspector does, which is request a parse
        # of the text of a datum into 'text' and various code snippets,
        # and then evaluating the code one-by-one.

        from parse import get_text_and_commands
        tac = get_text_and_commands(cmd2)
        self.assertEqual(
            [('evaluation', 'foo'),
             ('evaluation', 'bar'),
             ('declaration', ('foo', '42'))], tac)

        from parse import evaluate
        result = evaluate(tac[0][1], grid, clip=cmd2_clip)
        self.assertEqual([('value', 42)], result)
        result = evaluate(tac[1][1], grid, clip=cmd2_clip)
        self.assertEqual([('value', 64)], result)
示例#4
0
    def refresh(self):
        grid = self.inspector.grid
        selection_clip = grid.get_cursor_clip()
        self.clip = selection_clip
        marker_clip = grid.get_secondary_cursor_clip()
        value = ''

        # Set the score inputs, or disable them.
        if not (selection_clip and marker_clip):
            # Clear and disable the inputs.
            self.number_text_edit.setEnabled(False)
            self.number_text_edit.setText('')
            self.other_number_text_edit.setEnabled(False)
            self.other_number_text_edit.setText('')
        else:
            # Lookup values and set them in enabled inputs
            selection_key = selection_clip.datum.model.key
            marker_key = marker_clip.datum.model.key
            relationships = grid.model.relationships
            s_g_m = relationships.get(selection_key, {}).get(marker_key, '')
            m_g_s = relationships.get(marker_key, {}).get(selection_key, '')
            self.number_text_edit.setEnabled(True)
            self.number_text_edit.setText(s_g_m)
            self.other_number_text_edit.setEnabled(True)
            self.other_number_text_edit.setText(m_g_s)

        if selection_clip:
            pos = selection_clip.model.edit_cursor_position
            # Note that doing this changes the cursor, and triggers
            # the cursor changing thing... we need to disconnect and then
            # connect to eliminate this bounce, for now a hack.
            self.text_edit.setText(selection_clip.datum.model.data)
            #self.eq_text_edit.setText(selection_clip.datum.model.data)
            cursor = self.text_edit.textCursor()
            cursor.setPosition(pos)
            self.text_edit.setTextCursor(cursor)

            whole_text = selection_clip.datum.model.data
            self.eq_text_edit.clear()
            cursor = self.eq_text_edit.textCursor()
            for kind, text in get_text_and_commands(whole_text):
                if kind == 'text':
                    cursor.insertText(text)
                elif kind == 'equation':
                    pixmap = render_equation_to_pixmap(text)
                    width = 200  #self.text_edit.width()
                    pixmap = pixmap.scaled(width, width, Qt.KeepAspectRatio)
                    image = QImage(pixmap)
                    cursor.insertImage(image)
        else:
            self.text_edit.setText('')
            self.eq_text_edit.setText('')

        if marker_clip:
            pos = marker_clip.model.edit_cursor_position
            self.marker_edit.setText(marker_clip.datum.model.data)
            cursor = self.marker_edit.textCursor()
            cursor.setPosition(pos)
            self.marker_edit.setTextCursor(cursor)
        else:
            self.marker_edit.setText('')

        self.focus_label.setText('focus: {0}'.format(self.last_focus_name))
        m = self.inspector.grid.model
        self.scroll_x_label.setText('scroll: {0}, {1}'.format(
            m.x_offset, m.y_offset))
        # These coordinates are screen relative
        m = self.inspector.grid.main_cursor.model
        self.label.setText(
            '<span style="color:#ff0000;">selection</span>: {}, {}'.format(
                m.x + self.inspector.grid.model.x_offset,
                m.y + self.inspector.grid.model.y_offset))
        # These coordinates are already absolute
        m = self.inspector.grid.secondary_cursor.model
        self.marker_label.setText(
            '<span style="color:{};">home row</span>: {}, {}'.format(
                GRID_BACKGROUND_HOMEROW, m.x, m.y))

        # Set the hierarchy labels.
        parent_texts = []
        selection_parent_name = '<none>'
        if selection_clip:
            parent_key = selection_clip.datum.model.parent
            if parent_key:
                selection_parent_name = get(parent_key).model.name
            if parent_key and marker_clip:
                if marker_clip.datum.model.key == parent_key:
                    parent_texts.append('▲ parent of ▼')
        self.selection_parent_label.setText(
            'parent: {0}'.format(selection_parent_name))
        marker_parent_name = '<none>'
        if marker_clip:
            parent_key = marker_clip.datum.model.parent
            if parent_key:
                marker_parent_name = get(parent_key).model.name
            if parent_key and selection_clip:
                if selection_clip.datum.model.key == parent_key:
                    parent_texts.append('▼ parent of ▲')
        self.marker_parent_label.setText(
            'parent: {0}'.format(marker_parent_name))

        if parent_texts:
            self.parent_label.setText('hierarchy: ' + ', '.join(parent_texts))
        else:
            self.parent_label.setText('hierarchy: ▲ unrelated ▼')
示例#5
0
    def refresh(self):
        self.clip = self.grid.get_clip_at(self.screen_x, self.screen_y)
        if self.clip:
            name = self.clip.datum.model.name
            data = self.clip.datum.model.data
        else:
            name = ''
            data = ''
        offset_y = self.screen_y + self.grid.model.y_offset
        is_home_row = offset_y == 0
        if data or name:
            if is_home_row:
                self.background = CLIP_BACKGROUND_HOMEROW
            else:
                self.background = CLIP_BACKGROUND
        else:
            if is_home_row:
                self.background = GRID_BACKGROUND_HOMEROW
            else:
                self.background = GRID_BACKGROUND
        self.style_sheet.set('background', self.background)

        main_cursor = self.grid.main_cursor
        secondary_cursor = self.grid.secondary_cursor
        # Screen coordinates
        m_x = main_cursor.model.x
        m_y = main_cursor.model.y
        # Absolute coordinates
        s_x = secondary_cursor.model.x - self.grid.model.x_offset
        s_y = secondary_cursor.model.y - self.grid.model.y_offset
        main_on = m_x == self.screen_x and m_y == self.screen_y
        secondary_on = s_x == self.screen_x and s_y == self.screen_y
        # Taking this out for a moment -- REMOVE TO PUT 2nd CURSOR BACK
        secondary_on = False
        if main_on and secondary_on:
            self.style_sheet.set('border', '2px dashed purple')
        elif main_on:
            self.style_sheet.set('border', '2px dashed red')
        elif secondary_on:
            self.style_sheet.set('border', '2px dashed blue')
        else:
            self.style_sheet.set('border',
                                 '2px solid {0}'.format(self.background))
        self.setStyleSheet(self.style_sheet.render())
        if data != self.text_edit.toPlainText():
            self.text_edit.setText(data)
        if name != self.title_label.text():
            self.title_label.setText(name)

        if not self.clip:
            self.left_score.setStyleSheet("background: rgba(0,0,0,0%)")
            self.left_score.display('')
            self.right_score.setStyleSheet("background: rgba(0,0,0,0%)")
            self.right_score.display('')
            return

        from controllers import _m, _term_to_index, _embedding, _lt
        from torch.autograd import Variable
        clip_datum_key = self.clip.model.datum_key
        clip_datum_text = get(clip_datum_key).model.data
        clip_term_id = _term_to_index[clip_datum_text]
        # Left side is distance from this to selection
        selection_score = None
        selection_clip = self.grid.get_cursor_clip()
        if selection_clip:
            selection_datum_key = selection_clip.model.datum_key
            selection_datum_text = get(selection_datum_key).model.data
            selection_term_id = _term_to_index[selection_datum_text]
            s_e = Variable(_lt[selection_term_id].expand_as(_embedding),
                           volatile=True)
            _dists = _m.dist()(s_e, _embedding).data.cpu().numpy().flatten()
            selection_score = round(float(_dists[clip_term_id]), 5)
        if selection_score is None:
            left_score_text = ''
        else:
            left_score_text = str(selection_score)
        if selection_score is None:
            self.left_score.setStyleSheet("background: rgba(0,0,0,0%)")
        else:
            self.left_score.setStyleSheet("background: 'red'")
        self.left_score.display(left_score_text)

        # Right side is distance from this to home
        home_score = None
        # remember this is a clip.view, not a clip... we need to lookup in
        # absolute.
        absolute_x = self.screen_x + self.grid.model.x_offset
        coords = (absolute_x, 0)
        home_clip = self.grid.coordinates_to_clip[coords]

        if home_clip:
            home_datum_key = home_clip.model.datum_key
            home_datum_text = get(home_datum_key).model.data
            home_term_id = _term_to_index[home_datum_text]
            s_e = Variable(_lt[home_term_id].expand_as(_embedding),
                           volatile=True)
            _dists = _m.dist()(s_e, _embedding).data.cpu().numpy().flatten()
            home_score = round(float(_dists[clip_term_id]), 5)
        if home_score is None:
            right_score_text = ''
        else:
            right_score_text = str(home_score)
        if home_score is None:
            self.right_score.setStyleSheet("background: rgba(0,0,0,0%)")
        else:
            self.right_score.setStyleSheet(
                "background: '{}'".format(GRID_BACKGROUND_HOMEROW))
        self.right_score.display(right_score_text)
示例#6
0
    def setup(self):
        log.info('MainWindow setup')
        from app import get_application
        # Menu setup
        exit_action = QAction('&Exit', self)
        exit_action.setShortcut('Ctrl+Q')
        exit_action.setStatusTip('Quit Wren')
        exit_action.triggered.connect(
            QCoreApplication.instance().quit)  #qApp.quit)

        import_action = QAction('&Import', self)
        import_action.setShortcut('Ctrl+I')
        import_action.setStatusTip('Import notes')
        import_action.triggered.connect(self.show_import_dialog)

        # Position, resize and decorate the window
        self.center()

        # Set to a large size in the desktop.
        log.info("getting window geometry...")
        geo = get_application().app.primaryScreen().size()
        #geo = QDesktopWidget().availableGeometry()
        log.info("... got {0} x {1}".format(geo.width(), geo.height()))
        x = geo.width() * 0.07
        width = geo.width() - (2 * x)
        y = geo.height() * 0.04 + 50
        height = geo.height() - (2 * y)
        log.info("setGeometry({0}, {1}, {2}, {3})".format(x, y, width, height))
        self.setGeometry(x, y, width, height)

        import wren
        import math
        grid_width = max(1, math.floor(width * .72 / wren.CLIP_WIDTH))
        grid_height = max(1, math.floor(height / wren.CLIP_HEIGHT))
        if wren.GRID_WIDTH is not None:
            grid_width = wren.GRID_WIDTH
        if wren.GRID_HEIGHT is not None:
            grid_height = wren.GRID_HEIGHT
        log.info('gridwidth {0}, gridheight {1}'.format(
            grid_width, grid_height))

        # This is accessed by other widgets when they need a progress bar.
        # see import mammals, and make_ranked_clips
        self.progress = QProgressDialog(self)
        self.progress.setModal(True)
        self.progress.setRange(0, 220)
        self.progress.setMinimumDuration(250)
        #self.progress.canceled.connect(self.thread.requestInterruption)
        self.progress.reset()

        self.setWindowTitle('Wren')
        log.info("creating Grid and Inspector")
        self.h_box = QHBoxLayout()
        self.grid = get(get_application().app_model.current_grid,
                        width=grid_width,
                        height=grid_height,
                        status_bar=self.statusBar())
        import controllers
        self.inspector = controllers.Inspector(None)
        controllers.get_controller_id_map().set('main_inspector',
                                                self.inspector)
        self.inspector.setup(self.grid)

        self.h_box.addWidget(self.grid.view)
        self.h_box.addWidget(self.inspector.view)

        self.grid.view.clip_changed.connect(self.inspector.view.refresh)
        self.grid.view.cursor_changed.connect(self.inspector.view.refresh)
        self.grid.view.secondary_cursor_changed.connect(
            self.inspector.view.refresh)

        w = QWidget(self)
        w.setLayout(self.h_box)
        self.setCentralWidget(w)

        delete_column_action = QAction('Delete Column', self)
        delete_column_action.setShortcut('Ctrl+W')
        delete_column_action.setStatusTip('Delete Column')
        delete_column_action.triggered.connect(self.grid.delete_cursor_column)

        make_ranked_clips_action = QAction('Ranked Column', self)
        make_ranked_clips_action.setShortcut('Ctrl+Return')
        make_ranked_clips_action.setStatusTip(
            'Insert new column sorted by rank relative to selection')
        make_ranked_clips_action.triggered.connect(
            self.grid.make_ranked_clips_1)

        find_clip_action = QAction('Find', self)
        find_clip_action.setShortcut('Ctrl+S')  # F is navigational atm.
        find_clip_action.setStatusTip('Find Clip closest matching string')
        find_clip_action.triggered.connect(self.grid.do_find)

        delete_clip_action = QAction('Delete Clip', self)
        delete_clip_action.setShortcut('Ctrl+Backspace')
        delete_clip_action.setStatusTip('Delete Clip (but not its Datum)')
        delete_clip_action.triggered.connect(self.grid.delete_clip)

        copy_clip_action = QAction('Copy Clip', self)
        copy_clip_action.setShortcut('Ctrl+C')
        copy_clip_action.setStatusTip("Copy current Clip's Datum to clipboard")
        copy_clip_action.triggered.connect(self.grid.copy_clip)

        cut_clip_action = QAction('Cut Clip', self)
        cut_clip_action.setShortcut('Ctrl+X')
        cut_clip_action.setStatusTip("Cut current Clip's Datum to clipboard")
        cut_clip_action.triggered.connect(self.grid.cut_clip)

        paste_clip_action = QAction('Paste Clip', self)
        paste_clip_action.setShortcut('Ctrl+V')
        paste_clip_action.setStatusTip("Make new Clip from clipboard Datum")
        paste_clip_action.triggered.connect(self.grid.paste_clip)

        archive_datum_action = QAction('Archive Datum', self)
        archive_datum_action.setShortcut('Ctrl+Delete')
        archive_datum_action.setStatusTip('Remove Datum from Grid')
        archive_datum_action.triggered.connect(self.grid.archive_datum)

        refresh_column_action = QAction('Refresh Column', self)
        refresh_column_action.setShortcut('Ctrl+R')
        refresh_column_action.setStatusTip('Re-sort the current column')
        refresh_column_action.triggered.connect(
            self.grid.refresh_selected_column)

        scroll_cursor_right_action = QAction('Scroll Cursor Right', self)
        scroll_cursor_right_action.setShortcut('Ctrl+G')
        scroll_cursor_right_action.setStatusTip(
            "Scroll such that Selection's current Clip is center right")
        scroll_cursor_right_action.triggered.connect(
            self.grid.scroll_cursor_right)

        scroll_cursor_center_action = QAction('Scroll Cursor Center', self)
        scroll_cursor_center_action.setShortcut('Ctrl+F')
        scroll_cursor_center_action.setStatusTip(
            "Scroll such that Selection's current Clip is center center")
        scroll_cursor_center_action.triggered.connect(
            self.grid.scroll_cursor_center)

        scroll_cursor_left_action = QAction('Scroll Cursor Left', self)
        scroll_cursor_left_action.setShortcut('Ctrl+D')
        scroll_cursor_left_action.setStatusTip(
            "Scroll such that Selection's current Clip is center left")
        scroll_cursor_left_action.triggered.connect(
            self.grid.scroll_cursor_left)

        scroll_column_action = QAction('Scroll Column', self)
        scroll_column_action.setShortcut('Ctrl+L')
        scroll_column_action.setStatusTip(
            "Scroll to Column top, home or bottom (cyclic)")
        scroll_column_action.triggered.connect(self.grid.do_column_scroll)

        cycle_parentage_action = QAction('Cycle Parentage', self)
        cycle_parentage_action.setShortcut('Ctrl+P')
        cycle_parentage_action.setStatusTip(
            "Cycle through parentage choices between Selection and Marker")
        cycle_parentage_action.triggered.connect(self.grid.do_cycle_parentage)

        import_algebra_action = QAction('Import Tensor Algebra Notes', self)
        import_algebra_action.setShortcut('Ctrl+A')
        import_algebra_action.setStatusTip("Import documents/tensors.txt")
        import_algebra_action.triggered.connect(
            self.grid.view.import_algebra_notes)

        import_mammals_action = QAction('Import Mammals Closure', self)
        import_mammals_action.setShortcut('Ctrl+M')
        import_mammals_action.setStatusTip("Import mammals.pth")
        import_mammals_action.triggered.connect(
            self.grid.view.import_mammals_closure)

        menubar = self.menuBar()
        menubar.setNativeMenuBar(False)  # For in-window menu on a Mac
        file_menu = menubar.addMenu('&File')
        file_menu.addAction(import_action)
        file_menu.addAction(exit_action)

        grid_menu = menubar.addMenu('&Grid')
        grid_menu.addAction(import_mammals_action)
        grid_menu.addAction(import_algebra_action)
        grid_menu.addAction(delete_column_action)
        grid_menu.addAction(make_ranked_clips_action)
        grid_menu.addAction(find_clip_action)
        grid_menu.addAction(delete_clip_action)
        grid_menu.addAction(copy_clip_action)
        grid_menu.addAction(cut_clip_action)
        grid_menu.addAction(paste_clip_action)
        grid_menu.addAction(archive_datum_action)
        grid_menu.addAction(refresh_column_action)
        grid_menu.addAction(scroll_cursor_right_action)
        grid_menu.addAction(scroll_cursor_center_action)
        grid_menu.addAction(scroll_cursor_left_action)
        grid_menu.addAction(scroll_column_action)
        grid_menu.addAction(cycle_parentage_action)

        # Statusbar setup
        self.statusBar().showMessage('Ready')

        # Toolbar setup
        self.toolbar = self.addToolBar('Exit')
        self.toolbar.addAction(exit_action)
        self.toolbar.addAction(import_action)

        self.toolbar.addAction(import_algebra_action)
        self.toolbar.addAction(import_mammals_action)
        self.toolbar.addAction(delete_column_action)
        self.toolbar.addAction(make_ranked_clips_action)
        self.toolbar.addAction(delete_clip_action)
        self.toolbar.addAction(copy_clip_action)
        self.toolbar.addAction(cut_clip_action)
        self.toolbar.addAction(paste_clip_action)
        self.toolbar.addAction(archive_datum_action)
        self.toolbar.addAction(refresh_column_action)
        self.toolbar.addAction(scroll_cursor_right_action)
        self.toolbar.addAction(scroll_cursor_center_action)
        self.toolbar.addAction(scroll_cursor_left_action)
        self.toolbar.addAction(scroll_column_action)
        self.toolbar.addAction(cycle_parentage_action)
        self.show()