def tearDown(self): import controllers controllers.get_controller_id_map()._reset() import model model.get_model_id_map()._reset() import app app._APPLICATION = None app.get_application().init_data()
def setUp(self): import model model._STORAGE = model.WrenData.initialize(file_name=':memory:') model.get_model_id_map()._reset() import controllers controllers.get_controller_id_map()._reset() import app app._APPLICATION = None app.get_application().init_data()
def keyPressEvent(self, event): if event.key() in {Qt.Key_Right, Qt.Key_Left, Qt.Key_Up, Qt.Key_Down}: # Focus to Grid from app import get_application grid = get_application().main_window.grid grid.view.setFocus(True) # Re-emit the event (or equivalent) get_application().main_window.key_pressed.emit(event) # Do not let the QLineEdit handle the key press. return super(KeyPressLineEdit, self).keyPressEvent(event)
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)
def on_key_press(self, event): from app import get_application if self.grid != get_application().main_window.grid: # Not this cursor. return modifiers = QApplication.keyboardModifiers() # Note modifiers can be OR'd together to check for combos. shift = modifiers & Qt.ShiftModifier ctrl = modifiers & Qt.ControlModifier if ctrl: return meant_for_us = (self.model.name == 'main' and not shift) or \ (self.model.name == 'secondary' and shift) if not meant_for_us: return key = event.key() if key == Qt.Key_Right: self.move_right() elif key == Qt.Key_Left: self.move_left() elif key == Qt.Key_Up: self.move_up() elif key == Qt.Key_Down: self.move_down() elif key == Qt.Key_Return and not shift and not ctrl: # Set Focus on the cursor's Clip. self.grid.status_bar.showMessage('Editing Clip') self.grid.set_clip_focus(self.model.x, self.model.y) elif key == Qt.Key_Escape: self.grid.status_bar.showMessage('Edit Clip complete') self.grid.set_cursor_focus() self.grid.view.clip_changed.emit()
def __init__(self, grid, width, height): super().__init__() self.grid_layout = None self.grid = grid self.grid_width = width self.grid_height = height from app import get_application self.window = get_application().main_window self.coordinates_to_clip = {} # Screen Coordinates. self.grid_layout = QGridLayout() self.grid_layout.setSpacing(0) self.setLayout(self.grid_layout) self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self.setFocusPolicy(Qt.TabFocus) for screen_x in range(self.grid_width): for screen_y in range(self.grid_height): clip_view = ClipView(self, None, self.grid, screen_x, screen_y) # Note addWidget is y, x self.grid_layout.addWidget(clip_view, screen_y, screen_x) self.coordinates_to_clip[screen_x, screen_y] = clip_view self.clip_changed.connect(clip_view.refresh) self.installEventFilter(self) self.clip_changed.connect(self.refresh) self.window.key_pressed.connect(self.on_key_press) self.refresh()
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')
def set_focus(self, screen_x, screen_y): """Edit given location, creating Clip and Datum if needed.""" clip_view = self.coordinates_to_clip[screen_x, screen_y] # minor kludge, until you create a clip it doesn't show the background. clip_view.background = CLIP_BACKGROUND clip_view.style_sheet.set('background', clip_view.background) clip_view.setStyleSheet(clip_view.style_sheet.render()) from app import get_application inspector = get_application().main_window.inspector inspector.set_focus()
def set_cursor_focus(self): """Called for Focus on Grid for moving Cursors with arrows.""" from app import get_application inspector = get_application().main_window.inspector try: inspector.view.text_edit.cursorPositionChanged.disconnect( inspector.view.on_cursor_position_change) except TypeError: log.warn('TypeError in inspector disconnect') self.view.set_cursor_focus()
def change_offset(self, delta_x, delta_y, description=''): """change the current scroll position by the given amount""" if description: self.status_bar.showMessage('scroll {}'.format(description)) self.model.x_offset += delta_x self.model.y_offset += delta_y self.model.save() self.view.refresh() from app import get_application inspector = get_application().main_window.inspector inspector.view.refresh()
def get_debug_preview_server(port=PREVIEW_HTTP_PORT_DEFAULT, host=PREVIEW_HTTP_HOST_DEFAULT): """ Configure the app for debug/development mode and create a WSGI server object. :param port: :param host: :return: """ config = get_debug_preview_config() wsgi_application = get_application(config) return make_server(host, int(port), wsgi_application)
def run(obj: dict, port, host): """Runs the development server""" if not obj["DEBUG"] and not obj["TESTING"]: click.echo("Run from CLI cannot be used in production.", err=True) sys.exit(1) elif obj["TESTING"]: sys.exit(0) from .server_runner import run_app from app import get_application return run_app(get_application(config), port, host)
def __init__(self, data, name=None, key=None, last_changed=None, parent=None): super().__init__(key=key) if name is None: from app import get_application name = get_application().get_next_name() self.name = name self.data = data if last_changed is None: last_changed = datetime.now(tz=pytz.utc) self.last_changed = last_changed self.parent = parent
def on_key_press(self, event): modifiers = QApplication.keyboardModifiers() # Note modifiers can be OR'd together to check for combos. key = event.key() shift = modifiers & Qt.ShiftModifier ctrl = modifiers & Qt.ControlModifier if ctrl: if key == Qt.Key_Right: self.grid.change_offset(1, 0, 'right') elif key == Qt.Key_Left: self.grid.change_offset(-1, 0, 'left') elif key == Qt.Key_Down: self.grid.change_offset(0, 1, 'down') elif key == Qt.Key_Up: self.grid.change_offset(0, -1, 'up') else: # Lets you type numbers when Grid has focus and it sets the score # in the number input and gives focus to the number input. num = { Qt.Key_Period: '.', Qt.Key_0: '0', Qt.Key_1: '1', Qt.Key_2: '2', Qt.Key_3: '3', Qt.Key_4: '4', Qt.Key_5: '5', Qt.Key_6: '6', Qt.Key_7: '7', Qt.Key_8: '8', Qt.Key_9: '9' } try: c = num[key] except KeyError: return from app import get_application inspector = get_application().main_window.inspector if inspector.view.number_text_edit.isEnabled(): line_edit = inspector.view.number_text_edit line_edit.setFocus(True) line_edit.setText(c)
def setup(self): super().setup() self.grid = get(self.model.grid_key) from app import get_application get_application().main_window.key_pressed.connect(self.on_key_press)
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)
def remove(self, element): del self.sheet[element] class IDMap: """Map of datum key to its Controller""" def __init__(self): # Map of key to object. self.id_map = {} def get(self, key): return self.id_map.get(key) def set(self, key, obj): self.id_map[key] = obj def _reset(self): """Reset map for testing purposes only""" self.id_map = {} # -- Main --------------------------------------------------------------------- if __name__ == '__main__': # Confirm data storage is initialized (need: user to name the session.) from app import get_application wren = get_application() # Creates application if does not exist. wren.init_ui() sys.exit(wren.run())
def make_ranked_clips(self, main_cursor=True, secondary_cursor=False, lexical=False, in_place=False, force_homerow=False): # If in-place is true it re-sorts / re-creates the current column. # Note: This function is old and crusty and poorly documented. At the # moment it is the "sort" used when you give the ctrl-enter command, # it should make a new column if needed, and position the clips # according to our latest rules/thinking on clip-sorting. start_time = datetime.now() if not main_cursor and not secondary_cursor: raise ValueError homerow_screen_y = -self.model.y_offset clip = None if force_homerow: # If True, use screen from main cursor and clip from home row only. screen_x = self.main_cursor.model.x absolute_x = screen_x + self.model.x_offset clip = self.coordinates_to_clip.get((absolute_x, 0)) else: if secondary_cursor: screen_x = self.secondary_cursor.model.x clip = self.get_secondary_cursor_clip() if main_cursor: screen_x = self.main_cursor.model.x clip = self.get_cursor_clip() if not clip: # If we are on the home-row then this gives a 'null-search' if self.main_cursor.model.y == homerow_screen_y: self.status_bar.showMessage('Make Ranked Clips - null search') positives = [] # list of (score, key) tuples negatives = [] # Should be empty, nothing is its own parent. unscoreds = [] for datum_key in self.active_datums: try: score = self.model.relationships[datum_key][datum_key] score = float(score) except (KeyError, ValueError): score = None if score is not None: positives.append((score, datum_key)) else: unscoreds.append(datum_key) # Sort by score descending positives = [x[1] for x in sorted(positives, reverse=True)] negatives = [x[1] for x in sorted(negatives)] unscoreds = sorted(unscoreds, key=lambda x: get(x).model.last_changed) self.insert_column(screen_x) for i, datum_key in enumerate(positives + [None] + unscoreds): if datum_key is None: continue datum = get(datum_key) self.new_clip(screen_x, homerow_screen_y + i + 1, datum, 0) for i, datum_key in enumerate(negatives): datum = get(datum_key) self.new_clip(screen_x, homerow_screen_y - i - 1, datum, 0) self.main_cursor.model.y = homerow_screen_y self.main_cursor.model.x = screen_x self.main_cursor.model.save() self.secondary_cursor.model.y = 0 self.secondary_cursor.model.x = screen_x + self.model.x_offset self.secondary_cursor.model.save() self.view.refresh() # Perhaps someday we will refactor this monstrosity, # TODAY IS NOT THAT DAY! return self.status_bar.showMessage( 'Make Ranked Clips fail - no Clip selected') return self.status_bar.showMessage('Make Ranked Clips on Clip {}'.format( clip.datum.model.name)) center_y = math.floor(self.grid_height / 2.0) # This moves the Cursor's column and everything to the left of it # over one, a blank column remains at screen_x. if in_place: # Remove the current column. absolute_x = screen_x + self.model.x_offset if absolute_x in self.y_upper_bounds: for absolute_y in range(self.y_upper_bounds[absolute_x], self.y_lower_bounds[absolute_x] + 1): coords = (absolute_x, absolute_y) if coords not in self.coordinates_to_clip: continue c = self.coordinates_to_clip[coords] del self.coordinates_to_clip[coords] self.model.delete_clip(c.model) del self.y_upper_bounds[absolute_x] del self.y_lower_bounds[absolute_x] else: self.insert_column(screen_x) # Now the Cursor's (former) Clip is at screen_x-1, and screen_x is # where the new Clips are going to go. # Get the ranked Clips. # - - - start old notes - - - # These notes are old, it's what I changed when I went to mammals. # score is probabilty of the primary conditioned on the secondary. # ApBs - prob A given B = .3 # CpBs - prob C given B = .2 # # Move primary to B, hit ctrl-enter # # B copies to home row of next column # under is A, # under is C # model.relationships is stort AgivenB, [A][B] # Score and Sort is by Primary(A) given Secondary(B) # so you look up [P][S] # and you sort looking up item given homerow, [I][H] # Here we sort # ctrl-enter is: # probabilty of the sorted conditioned on the homerow # - - - end old notes - - - clip_datum_key = clip.model.datum_key # Map of ITEM datum_key with float-value of P(I|Homerow) positives = [] unscoreds = [] # find all 'parents' of clip datum key # This is now to - do, because mammals is different than parents, it # uses a "is a kind of" relationship. # We have ideas for using the distance function, but for now, it's # nixed. # - - - old parent keys - - - # parent_keys = [] # parent_keys_set = set(parent_keys) # current_datum_key = clip_datum_key # while True: # d = get(current_datum_key) # current_datum_key = d.model.parent # if current_datum_key and current_datum_key not in parent_keys_set: # parent_keys.append(current_datum_key) # parent_keys_set = set(parent_keys) # else: # break # - - - end old parent keys - - - # This is the new mammal-based code. # Get the term_id for the datum text (it is expected to # exactly match a term in the mammals set or the score will # be 0.0.) # Note: Could cache the dist-calculations clip_datum_text = get(clip_datum_key).model.data clip_term_id = _term_to_index[clip_datum_text] s_e = Variable(_lt[clip_term_id].expand_as(_embedding), volatile=True) _dists = _m.dist()(s_e, _embedding).data.cpu().numpy().flatten() from app import get_application progress = get_application().main_window.progress old_min_time = progress.minimumDuration() progress.setMinimumDuration( max(0, old_min_time - (datetime.now() - start_time).seconds * 1000)) num = len(self.active_datums) progress.setRange(0, num) progress.reset() progress.setLabelText('Getting scores for {} datums'.format(num)) for i, datum_key in enumerate(self.active_datums): progress.setValue(i) if datum_key == clip_datum_key: # or datum_key in parent_keys_set: continue try: datum_text = get(datum_key).model.data datum_term_id = _term_to_index[datum_text] score = _dists[datum_term_id] score = float(score) except (KeyError, ValueError): score = None if score is not None: positives.append((score, datum_key)) else: unscoreds.append(datum_key) progress.setRange(0, 2) progress.setMinimumDuration( max(0, old_min_time - (datetime.now() - start_time).seconds * 1000)) progress.reset() progress.setLabelText('Sorting scores') # Sort by score ascending (smaller distance, closer match) positives = [x[1] for x in sorted(positives)] progress.setValue(1) #negatives = parent_keys #[x[1] for x in sorted(negatives)] unscoreds = sorted(unscoreds, key=lambda x: get(x).model.last_changed) progress.setValue(2) #self.insert_column(screen_x) # already done it above if needed datums = positives + [None] + unscoreds progress.setRange(0, len(datums) - 1) progress.setMinimumDuration( max(0, old_min_time - (datetime.now() - start_time).seconds * 1000)) progress.reset() progress.setLabelText('Creating {} Clips'.format(len(datums))) self.new_clip(screen_x, homerow_screen_y, clip.datum, 0, emit=False) for i, datum_key in enumerate(datums): progress.setValue(i + 1) if datum_key is None: continue datum = get(datum_key) self.new_clip(screen_x, homerow_screen_y + i + 1, datum, 0, emit=False) self.view.clip_changed.emit() #for i, datum_key in enumerate(negatives): # datum = get(datum_key) # self.new_clip(screen_x, homerow_screen_y - i - 1, datum, 0) self.main_cursor.model.y = homerow_screen_y self.main_cursor.model.x = screen_x self.main_cursor.model.save() self.secondary_cursor.model.y = 0 self.secondary_cursor.model.x = screen_x + self.model.x_offset self.secondary_cursor.model.save() self._scroll_cursor(1, 1) progress.setMinimumDuration(old_min_time) progress.reset() self.view.refresh()
def test_generate_css(self): with mock.patch('scss.Scss') as Scss: get_application(generate_css=True) assert Scss.called
def app(): app = get_application(debug=True).test_client() return app
def test_generate_css(self): with mock.patch('scss.Scss') as Scss: get_application(generate_css=True) assert Scss.called
def app(config): return TestClient(get_application(config))
def import_mammals_closure(self): start_time = datetime.now() tsv = 'mammal_closure.tsv' # Get the word count for the tsv so we can have a nice progress bar. import subprocess cmd = ['wc', '-l', tsv] output = subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0] count = int(output.strip().split(b' ')[0]) from app import get_application progress = get_application().main_window.progress old_min_time = progress.minimumDuration() progress.setMinimumDuration( max(0, old_min_time - (datetime.now() - start_time).seconds * 1000)) progress.setRange(0, count) progress.reset() progress.setLabelText('Getting {} lines from {}'.format(count, tsv)) from poincare.data import slurp idx, objects = slurp('mammal_closure.tsv', progress=progress) # We use slurp because it will read the parentage out of the closure. from collections import defaultdict as ddict adjacency = ddict(set) count = len(idx) progress.setMinimumDuration( max(0, old_min_time - (datetime.now() - start_time).seconds * 1000)) progress.setLabelText('Making Adjacency of {} edges'.format(count)) progress.setRange(0, count + 1) progress.reset() for i in range(len(idx)): progress.setValue(i + 1) s, o, _ = idx[i] adjacency[s].add(o) adjacency = dict(adjacency) progress.setValue(count + 1) # This is a map of number (objects index) to "is a kind of" indexes import torch as th serialization = th.load('mammals.pth') datums_text = serialization['objects'] count = 0 text_to_index = {} text_to_clip = {} progress.setLabelText('Making {} Clips'.format(len(datums_text))) progress.setMinimumDuration( max(0, old_min_time - (datetime.now() - start_time).seconds * 1000)) progress.setRange(0, len(datums_text)) progress.reset() # Sort these by distance from 'mammal' from torch.autograd import Variable from controllers import _lt, _embedding, _term_to_index, _m # Mammal is term 29. s_e = Variable(_lt[29].expand_as(_embedding), volatile=True) _dists = _m.dist()(s_e, _embedding).data.cpu().numpy().flatten() positives = [] for i, datum_text in enumerate(datums_text): progress.setValue(i) term_id = _term_to_index[datum_text] score = _dists[term_id] score = float(score) positives.append((score, datum_text)) datums_text = [x[1] for x in sorted(positives)] for i, datum_text in enumerate(datums_text): progress.setValue(i + 1) text_to_index[datum_text] = i count += 1 #x, y = self.grid._get_next_coords() x = 0 y = i clip = self.grid.new_datum_and_clip(x - self.grid.model.x_offset, y - self.grid.model.y_offset, datum_text, 0, emit=False) text_to_clip[datum_text] = clip self.grid.status_bar.showMessage('new clips {}'.format(count)) # Set the parentage progress.setLabelText('Setting {} Parentages'.format(len(adjacency))) progress.setMinimumDuration( max(0, old_min_time - (datetime.now() - start_time).seconds * 1000)) progress.setRange(0, len(adjacency)) progress.reset() for i, (parent, children) in enumerate(adjacency.items()): progress.setValue(i) parent_text = objects[parent] parent_clip = text_to_clip[parent_text] parent_key = parent_clip.datum.model.key for child in children: child_text = objects[child] child_clip = text_to_clip[child_text] child_clip.datum.model.parent = parent_key child_clip.datum.model.save() self.clip_changed.emit() msg = "import took %s seconds" % (datetime.now() - start_time).seconds log.info(msg) self.grid.status_bar.showMessage(msg) progress.setMinimumDuration(old_min_time) progress.reset()
"""Test submissions endpoints""" from typing import Dict from typing import List from typing import Tuple import pytest from starlette.testclient import TestClient from truth.truth import AssertThat # type: ignore from app import get_application from tests.conftest import POPULATE_SUBMISSION_ID from tests.conftest import mock_auth application = get_application() client: TestClient = TestClient(application) application = mock_auth(application) submission_requests: List[Tuple[str, str, Dict[str, str], int]] = [ ("GET", f"/api/submissions/{str(POPULATE_SUBMISSION_ID)}/votes/", {}, 200), ("GET", f"/api/submissions/{str(POPULATE_SUBMISSION_ID)}/", {}, 200), ] @pytest.mark.parametrize( # pylint: disable=not-callable "method,endpoint,data,expected_status", submission_requests) # pylint: disable=too-many-arguments def test_endpoints( # type: ignore method: str, endpoint: str, data: Dict[str, str], expected_status: int,
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()