Skip to content

Commit

Permalink
WIP: Add Focus To Name feature and CommandPalette
Browse files Browse the repository at this point in the history
  • Loading branch information
MHendricks committed Dec 19, 2023
1 parent d8ff4f2 commit 725128f
Show file tree
Hide file tree
Showing 6 changed files with 168 additions and 5 deletions.
Empty file.
57 changes: 57 additions & 0 deletions preditor/gui/command_palette/command_palette.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import six
from Qt.QtCore import QPoint, Qt
from Qt.QtWidgets import QFrame, QHBoxLayout, QLineEdit, QShortcut

from .workbox_completer import WorkboxCompleter


class CommandPalette(QFrame):
def __init__(self, model, parent=None, **kwargs):
super(CommandPalette, self).__init__(parent=parent, **kwargs)
self.y_offset = 100
lyt = QHBoxLayout(self)
self.uiLineEDIT = QLineEdit(parent=self)
lyt.addWidget(self.uiLineEDIT)
self.setMinimumSize(400, self.sizeHint().height())
self.uiCloseSCT = QShortcut(
Qt.Key_Escape, self, context=Qt.WidgetWithChildrenShortcut
)
self.uiCloseSCT.activated.connect(self.hide)
self.uiLineCOMPL = WorkboxCompleter()
self.uiLineCOMPL.setCaseSensitivity(False)
self.uiLineCOMPL.setModel(model)
self.uiLineEDIT.setCompleter(self.uiLineCOMPL)
self.uiLineCOMPL.activated.connect(self.completed)
self.uiLineCOMPL.highlighted.connect(self.completer_selected)
# self.uiLineCOMPL.popup().clicked.connect(self.completed)
self.current_name = parent.name_for_workbox(parent.current_workbox())

def completed(self, name):
if isinstance(name, six.string_types):
self.current_name = name
else:
self.current_name = self.uiLineCOMPL.pathFromIndex(name)
self.hide()

def completer_selected(self, name):
self.parent().workbox_for_name(name.rstrip("/"), visible=True)

def hide(self):
# Close the popup if its open
self.uiLineCOMPL.popup().hide()
# Restore the original tab as the user didn't choose the new tab
self.completer_selected(self.current_name)
super(CommandPalette, self).hide()

def reposition(self):
pgeo = self.parent().geometry()
geo = self.geometry()
center = QPoint(pgeo.width() // 2, self.y_offset)
geo.moveCenter(center)
self.setGeometry(geo)

def popup(self):
self.reposition()
self.uiLineEDIT.setFocus(Qt.PopupFocusReason)
self.show()
self.uiLineCOMPL.complete()
9 changes: 9 additions & 0 deletions preditor/gui/command_palette/workbox_completer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from Qt.QtWidgets import QCompleter


class WorkboxCompleter(QCompleter):
def splitPath(self, path):
return path.split("/")

def pathFromIndex(self, index):
return self.model().pathFromIndex(index)
60 changes: 60 additions & 0 deletions preditor/gui/command_palette/workbox_item_model.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
from Qt.QtCore import Qt
from Qt.QtGui import QStandardItem, QStandardItemModel


def manager_items(manager):
for group_index in range(manager.count()):
group_name = manager.tabText(group_index)

tab_widget = manager.widget(group_index)
for tab_index in range(tab_widget.count()):
tab_name = tab_widget.tabText(tab_index)
yield group_name, tab_name, group_index, tab_index


class WorkboxItemModel(QStandardItemModel):
def __init__(self, manager, *args, **kwargs):
super(WorkboxItemModel, self).__init__(*args, **kwargs)
self.manager = manager

def pathFromIndex(self, index):
parts = [""]
while index.isValid():
parts.append(self.data(index, Qt.DisplayRole))
index = index.parent()
if len(parts) == 1:
return ""
return "/".join([x for x in parts[::-1] if x])


class WorkboxTreeItemModel(WorkboxItemModel):
def process(self):
root = self.invisibleRootItem()
prev_group = -1
for group_name, tab_name, group_index, _ in manager_items(self.manager):
if prev_group != group_index:
group_item = QStandardItem(group_name)
root.appendRow(group_item)
prev_group = group_index

tab_item = QStandardItem(tab_name)
group_item.appendRow(tab_item)

# for group in range(self.manager.count()):
# group_name = self.manager.tabText(group)
# group_item = QStandardItem(group_name)
# root.appendRow(group_item)

# tab_widget = self.manager.widget(group)
# for index in range(tab_widget.count()):
# tab_name = tab_widget.tabText(index)
# tab_item = QStandardItem(tab_name)
# group_item.appendRow(tab_item)


class WorkboxListItemModel(WorkboxItemModel):
def process(self):
root = self.invisibleRootItem()
for group_name, tab_name, _, _ in manager_items(self.manager):
group_item = QStandardItem('/'.join((group_name, tab_name)))
root.appendRow(group_item)
38 changes: 33 additions & 5 deletions preditor/gui/loggerwindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@
)
from ..delayable_engine import DelayableEngine
from ..gui import Dialog, Window, loadUi
from ..gui.command_palette.command_palette import CommandPalette
from ..gui.command_palette.workbox_item_model import WorkboxListItemModel
from ..logging_config import LoggingConfig
from ..utils import stylesheets
from .completer import CompleterMode
Expand Down Expand Up @@ -180,6 +182,8 @@ def __init__(self, parent, name=None, run_workbox=False):
self.uiGroup8ACT.triggered.connect(partial(self.gotoGroupByIndex, 8))
self.uiGroupLastACT.triggered.connect(partial(self.gotoGroupByIndex, -1))

self.uiFocusNameACT.triggered.connect(self.show_focus_name)

self.uiCommentToggleACT.triggered.connect(self.comment_toggle)

self.uiSpellCheckEnabledACT.toggled.connect(self.setSpellCheckEnabled)
Expand Down Expand Up @@ -306,7 +310,18 @@ def current_workbox(self):
return self.uiWorkboxTAB.current_groups_widget()

@classmethod
def workbox_for_name(cls, name, show=False):
def name_for_workbox(cls, workbox):
ret = []
logger = cls.instance()
index = logger.uiWorkboxTAB.currentIndex()
ret.append(logger.uiWorkboxTAB.tabText(index))
group_widget = logger.uiWorkboxTAB.currentWidget()
index = group_widget.currentIndex()
ret.append(group_widget.tabText(index))
return "/".join(ret)

@classmethod
def workbox_for_name(cls, name, show=False, visible=False):
"""Used to find a workbox for a given name. It accepts a string matching
the "{group}/{workbox}" format, or if True, the current workbox.
Expand All @@ -326,13 +341,19 @@ def workbox_for_name(cls, name, show=False):

# If name is a string, find first tab with that name
elif isinstance(name, six.string_types):
group, editor = name.split('/', 1)
index = logger.uiWorkboxTAB.index_for_text(group)
if index != -1:
tab_widget = logger.uiWorkboxTAB.widget(index)
split = name.split('/', 1)
if len(split) < 2:
return None
group, editor = split
group_index = logger.uiWorkboxTAB.index_for_text(group)
if group_index != -1:
tab_widget = logger.uiWorkboxTAB.widget(group_index)
index = tab_widget.index_for_text(editor)
if index != -1:
workbox = tab_widget.widget(index)
if visible:
tab_widget.setCurrentIndex(index)
logger.uiWorkboxTAB.setCurrentIndex(group_index)

if show and workbox:
workbox.__show__()
Expand Down Expand Up @@ -979,6 +1000,13 @@ def showEvent(self, event):
def show_workbox_options(self):
self.uiWorkboxSTACK.setCurrentIndex(WorkboxPages.Options)

@Slot()
def show_focus_name(self):
model = WorkboxListItemModel(manager=self.uiWorkboxTAB)
model.process()
w = CommandPalette(model, parent=self)
w.popup()

def updateCopyIndentsAsSpaces(self):
for workbox in self.uiWorkboxTAB.all_widgets():
workbox.__set_copy_indents_as_spaces__(
Expand Down
9 changes: 9 additions & 0 deletions preditor/gui/ui/loggerwindow.ui
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,7 @@
<addaction name="separator"/>
<addaction name="menuFocus_to_Group"/>
<addaction name="menuFocus_to_Tab"/>
<addaction name="uiFocusNameACT"/>
</widget>
<addaction name="uiScriptingMENU"/>
<addaction name="menuEdit"/>
Expand Down Expand Up @@ -930,6 +931,14 @@ at the indicated line in the specified text editor.
<string>Backup</string>
</property>
</action>
<action name="uiFocusNameACT">
<property name="text">
<string>Focus To Name</string>
</property>
<property name="shortcut">
<string>Ctrl+P</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>
Expand Down

0 comments on commit 725128f

Please sign in to comment.