mirror of https://github.com/KLayout/klayout.git
Search feature for layer list
To enable the search feature just type into the layer list. This change set also contains some more fixes: * Tab/Backtab now is functional also before the Display menu has been used the first time * Arrow keys work from the cell list again
This commit is contained in:
parent
08076de815
commit
5c414ef0be
|
|
@ -581,16 +581,6 @@ MainWindow::MainWindow (QApplication *app, const char *name)
|
|||
cp_frame_ly->insertSpacing (-1, 6);
|
||||
|
||||
// connect to the menus to provide the dynamic parts
|
||||
QMenu *edit_menu = mp_menu->menu ("edit_menu");
|
||||
tl_assert (edit_menu != 0);
|
||||
connect (edit_menu, SIGNAL (aboutToShow ()), this, SLOT (popup_menu_show ()));
|
||||
connect (edit_menu, SIGNAL (aboutToHide ()), this, SLOT (popup_menu_hide ()));
|
||||
|
||||
QMenu *zoom_menu = mp_menu->menu ("zoom_menu");
|
||||
tl_assert (zoom_menu != 0);
|
||||
connect (zoom_menu, SIGNAL (aboutToShow ()), this, SLOT (popup_menu_show ()));
|
||||
connect (zoom_menu, SIGNAL (aboutToHide ()), this, SLOT (popup_menu_hide ()));
|
||||
|
||||
QMenu *bookmark_menu = mp_menu->menu ("bookmark_menu");
|
||||
tl_assert (bookmark_menu != 0);
|
||||
connect (bookmark_menu, SIGNAL (aboutToShow ()), this, SLOT (bookmark_menu_show ()));
|
||||
|
|
@ -673,6 +663,11 @@ MainWindow::MainWindow (QApplication *app, const char *name)
|
|||
connect (&m_file_changed_timer, SIGNAL (timeout ()), this, SLOT (file_changed_timer()));
|
||||
m_file_changed_timer.setSingleShot (true);
|
||||
|
||||
// install timer for menu update
|
||||
connect (&m_menu_update_timer, SIGNAL (timeout ()), this, SLOT (update_action_states ()));
|
||||
m_menu_update_timer.setSingleShot (false);
|
||||
m_menu_update_timer.start (200);
|
||||
|
||||
connect (&lay::LayoutHandle::file_watcher (), SIGNAL (fileChanged (const QString &)), this, SLOT (file_changed (const QString &)));
|
||||
connect (&lay::LayoutHandle::file_watcher (), SIGNAL (fileRemoved (const QString &)), this, SLOT (file_removed (const QString &)));
|
||||
|
||||
|
|
@ -1695,9 +1690,6 @@ MainWindow::edits_enabled_changed ()
|
|||
for (std::vector<std::string>::const_iterator g = edit_grp.begin (); g != edit_grp.end (); ++g) {
|
||||
mp_menu->action (*g).set_enabled (enable);
|
||||
}
|
||||
|
||||
// call this to establish a consistent set of options on the menu entries
|
||||
popup_menu_show ();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -2664,123 +2656,73 @@ MainWindow::cm_zoom_out ()
|
|||
}
|
||||
|
||||
void
|
||||
MainWindow::popup_menu_hide ()
|
||||
MainWindow::update_action_states ()
|
||||
{
|
||||
// Enable all menu items as far as required on closing of the menu. Otherwise,
|
||||
// keyboard shortcuts are not effective when the window is closed and the actions are
|
||||
// left disabled.
|
||||
try {
|
||||
|
||||
BEGIN_PROTECTED
|
||||
if (mp_menu->is_valid ("edit_menu.undo")) {
|
||||
|
||||
if (mp_menu->is_valid ("edit_menu.undo")) {
|
||||
Action undo_action = mp_menu->action ("edit_menu.undo");
|
||||
undo_action.set_enabled (edits_enabled ());
|
||||
}
|
||||
Action undo_action = mp_menu->action ("edit_menu.undo");
|
||||
|
||||
if (mp_menu->is_valid ("edit_menu.redo")) {
|
||||
Action redo_action = mp_menu->action ("edit_menu.redo");
|
||||
redo_action.set_enabled (edits_enabled ());
|
||||
}
|
||||
std::string undo_txt (tl::to_string (QObject::tr ("&Undo")));
|
||||
bool undo_enable = false;
|
||||
if (current_view () && m_manager.available_undo ().first) {
|
||||
undo_txt += " - " + m_manager.available_undo ().second;
|
||||
undo_enable = true;
|
||||
}
|
||||
undo_action.set_title (undo_txt);
|
||||
undo_action.set_enabled (undo_enable && edits_enabled ());
|
||||
|
||||
if (mp_menu->is_valid ("edit_menu.copy")) {
|
||||
Action copy_action = mp_menu->action ("edit_menu.copy");
|
||||
copy_action.set_enabled (edits_enabled ());
|
||||
}
|
||||
|
||||
if (mp_menu->is_valid ("edit_menu.cut")) {
|
||||
Action cut_action = mp_menu->action ("edit_menu.cut");
|
||||
cut_action.set_enabled (edits_enabled ());
|
||||
}
|
||||
|
||||
if (mp_menu->is_valid ("edit_menu.paste")) {
|
||||
Action paste_action = mp_menu->action ("edit_menu.paste");
|
||||
paste_action.set_enabled (edits_enabled ());
|
||||
}
|
||||
|
||||
if (mp_menu->is_valid ("edit_menu.duplicate")) {
|
||||
Action paste_action = mp_menu->action ("edit_menu.duplicate");
|
||||
paste_action.set_enabled (edits_enabled ());
|
||||
}
|
||||
|
||||
if (mp_menu->is_valid ("zoom_menu.next_display_state")) {
|
||||
Action next_display_state_action = mp_menu->action ("zoom_menu.next_display_state");
|
||||
next_display_state_action.set_enabled (true);
|
||||
}
|
||||
|
||||
if (mp_menu->is_valid ("zoom_menu.last_display_state")) {
|
||||
Action last_display_state_action = mp_menu->action ("zoom_menu.last_display_state");
|
||||
last_display_state_action.set_enabled (true);
|
||||
}
|
||||
|
||||
END_PROTECTED
|
||||
}
|
||||
|
||||
void
|
||||
MainWindow::popup_menu_show ()
|
||||
{
|
||||
BEGIN_PROTECTED
|
||||
|
||||
if (mp_menu->is_valid ("edit_menu.undo")) {
|
||||
|
||||
Action undo_action = mp_menu->action ("edit_menu.undo");
|
||||
|
||||
std::string undo_txt (tl::to_string (QObject::tr ("&Undo")));
|
||||
bool undo_enable = false;
|
||||
if (current_view () && m_manager.available_undo ().first) {
|
||||
undo_txt += " - " + m_manager.available_undo ().second;
|
||||
undo_enable = true;
|
||||
}
|
||||
undo_action.set_title (undo_txt);
|
||||
undo_action.set_enabled (undo_enable && edits_enabled ());
|
||||
|
||||
}
|
||||
if (mp_menu->is_valid ("edit_menu.redo")) {
|
||||
|
||||
if (mp_menu->is_valid ("edit_menu.redo")) {
|
||||
Action redo_action = mp_menu->action ("edit_menu.redo");
|
||||
|
||||
Action redo_action = mp_menu->action ("edit_menu.redo");
|
||||
std::string redo_txt (tl::to_string (QObject::tr ("&Redo")));
|
||||
bool redo_enable = false;
|
||||
if (current_view () && m_manager.available_redo ().first) {
|
||||
redo_txt += " - " + m_manager.available_redo ().second;
|
||||
redo_enable = true;
|
||||
}
|
||||
redo_action.set_title (redo_txt);
|
||||
redo_action.set_enabled (redo_enable && edits_enabled ());
|
||||
|
||||
std::string redo_txt (tl::to_string (QObject::tr ("&Redo")));
|
||||
bool redo_enable = false;
|
||||
if (current_view () && m_manager.available_redo ().first) {
|
||||
redo_txt += " - " + m_manager.available_redo ().second;
|
||||
redo_enable = true;
|
||||
}
|
||||
redo_action.set_title (redo_txt);
|
||||
redo_action.set_enabled (redo_enable && edits_enabled ());
|
||||
|
||||
if (mp_menu->is_valid ("edit_menu.copy")) {
|
||||
Action copy_action = mp_menu->action ("edit_menu.copy");
|
||||
copy_action.set_enabled (current_view () && current_view ()->has_selection () && edits_enabled ());
|
||||
}
|
||||
|
||||
if (mp_menu->is_valid ("edit_menu.duplicate")) {
|
||||
Action copy_action = mp_menu->action ("edit_menu.duplicate");
|
||||
copy_action.set_enabled (current_view () && current_view ()->has_selection () && edits_enabled ());
|
||||
}
|
||||
|
||||
if (mp_menu->is_valid ("edit_menu.cut")) {
|
||||
Action cut_action = mp_menu->action ("edit_menu.cut");
|
||||
cut_action.set_enabled (current_view () && current_view ()->has_selection () && edits_enabled ());
|
||||
}
|
||||
|
||||
if (mp_menu->is_valid ("edit_menu.paste")) {
|
||||
Action paste_action = mp_menu->action ("edit_menu.paste");
|
||||
paste_action.set_enabled (! db::Clipboard::instance ().empty () && edits_enabled ());
|
||||
}
|
||||
|
||||
if (mp_menu->is_valid ("zoom_menu.next_display_state")) {
|
||||
Action next_display_state_action = mp_menu->action ("zoom_menu.next_display_state");
|
||||
next_display_state_action.set_enabled (has_next_display_state ());
|
||||
}
|
||||
|
||||
if (mp_menu->is_valid ("zoom_menu.last_display_state")) {
|
||||
Action last_display_state_action = mp_menu->action ("zoom_menu.last_display_state");
|
||||
last_display_state_action.set_enabled (has_last_display_state ());
|
||||
}
|
||||
|
||||
} catch (...) {
|
||||
// ignore exceptions
|
||||
}
|
||||
|
||||
if (mp_menu->is_valid ("edit_menu.copy")) {
|
||||
Action copy_action = mp_menu->action ("edit_menu.copy");
|
||||
copy_action.set_enabled (current_view () && current_view ()->has_selection () && edits_enabled ());
|
||||
}
|
||||
|
||||
if (mp_menu->is_valid ("edit_menu.duplicate")) {
|
||||
Action copy_action = mp_menu->action ("edit_menu.duplicate");
|
||||
copy_action.set_enabled (current_view () && current_view ()->has_selection () && edits_enabled ());
|
||||
}
|
||||
|
||||
if (mp_menu->is_valid ("edit_menu.cut")) {
|
||||
Action cut_action = mp_menu->action ("edit_menu.cut");
|
||||
cut_action.set_enabled (current_view () && current_view ()->has_selection () && edits_enabled ());
|
||||
}
|
||||
|
||||
if (mp_menu->is_valid ("edit_menu.paste")) {
|
||||
Action paste_action = mp_menu->action ("edit_menu.paste");
|
||||
paste_action.set_enabled (! db::Clipboard::instance ().empty () && edits_enabled ());
|
||||
}
|
||||
|
||||
if (mp_menu->is_valid ("zoom_menu.next_display_state")) {
|
||||
Action next_display_state_action = mp_menu->action ("zoom_menu.next_display_state");
|
||||
next_display_state_action.set_enabled (has_next_display_state ());
|
||||
}
|
||||
|
||||
if (mp_menu->is_valid ("zoom_menu.last_display_state")) {
|
||||
Action last_display_state_action = mp_menu->action ("zoom_menu.last_display_state");
|
||||
last_display_state_action.set_enabled (has_last_display_state ());
|
||||
}
|
||||
|
||||
END_PROTECTED
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -662,8 +662,7 @@ public slots:
|
|||
*/
|
||||
void intrinsic_mode_triggered ();
|
||||
|
||||
void popup_menu_show ();
|
||||
void popup_menu_hide ();
|
||||
void update_action_states ();
|
||||
void cancel ();
|
||||
void redraw ();
|
||||
void exit ();
|
||||
|
|
@ -900,6 +899,7 @@ private:
|
|||
tl::DeferredMethod<MainWindow> dm_do_update_menu;
|
||||
QTimer m_message_timer;
|
||||
QTimer m_file_changed_timer;
|
||||
QTimer m_menu_update_timer;
|
||||
std::string m_config_window_state;
|
||||
|
||||
std::string m_initial_technology;
|
||||
|
|
|
|||
|
|
@ -756,21 +756,6 @@ CellTreeModel::search_children (const tl::GlobPattern &pattern, CellTreeItem *it
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
CellTreeModel::search_children (const char *name, CellTreeItem *item)
|
||||
{
|
||||
int children = item->children ();
|
||||
for (int i = 0; i < children; ++i) {
|
||||
CellTreeItem *c = item->child (i);
|
||||
if (c) {
|
||||
if (c->name_equals (name)) {
|
||||
m_selected_indexes.push_back (model_index (c));
|
||||
}
|
||||
search_children (name, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QModelIndex
|
||||
CellTreeModel::locate (const char *name, bool glob_pattern, bool case_sensitive, bool top_only)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -238,7 +238,6 @@ private:
|
|||
void build_top_level ();
|
||||
void clear_top_level ();
|
||||
void search_children (const tl::GlobPattern &pattern, CellTreeItem *item);
|
||||
void search_children (const char *name, CellTreeItem *item);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -69,13 +69,9 @@ public:
|
|||
// --------------------------------------------------------------------
|
||||
// HCPCellTreeWidget implementation
|
||||
|
||||
HCPCellTreeWidget::HCPCellTreeWidget (QWidget *parent, const char *name)
|
||||
: QTreeView (parent)
|
||||
HCPCellTreeWidget::HCPCellTreeWidget (QWidget *parent, const char *name, QWidget *key_event_receiver)
|
||||
: QTreeView (parent), mp_key_event_receiver (key_event_receiver)
|
||||
{
|
||||
// Don't request focus: this leaves focus on the canvas and the arrow keys functional there
|
||||
// @@@ setFocusPolicy (Qt::NoFocus); -> solve differently!!!
|
||||
setFocusPolicy (Qt::ClickFocus);
|
||||
|
||||
// Allow dragging from here to
|
||||
setDragDropMode (QAbstractItemView::DragOnly);
|
||||
|
||||
|
|
@ -97,12 +93,24 @@ HCPCellTreeWidget::event (QEvent *event)
|
|||
return QTreeView::event (event);
|
||||
}
|
||||
|
||||
bool
|
||||
HCPCellTreeWidget::focusNextPrevChild (bool /*next*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
HCPCellTreeWidget::keyPressEvent (QKeyEvent *event)
|
||||
{
|
||||
QString t = event->text ();
|
||||
if (!t.isEmpty ()) {
|
||||
if (!t.isEmpty () && t[0].isPrint ()) {
|
||||
emit search_triggered (t);
|
||||
} else if (mp_key_event_receiver) {
|
||||
// send other key events to the alternative receiver - this way we can make the
|
||||
// view receive arrow keys for panning.
|
||||
QCoreApplication::sendEvent (mp_key_event_receiver, event);
|
||||
} else {
|
||||
return QTreeView::keyPressEvent (event);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -885,7 +893,7 @@ HierarchyControlPanel::do_update_content (int cv_index)
|
|||
header->setVisible (split_mode);
|
||||
cl_ly->addWidget (header);
|
||||
|
||||
HCPCellTreeWidget *cell_list = new HCPCellTreeWidget (cl_frame, "tree");
|
||||
HCPCellTreeWidget *cell_list = new HCPCellTreeWidget (cl_frame, "tree", mp_view->view_object_widget ());
|
||||
cl_ly->addWidget (cell_list);
|
||||
cell_list->setStyle (mp_tree_style.get ());
|
||||
cell_list->setModel (new CellTreeModel (cell_list, mp_view, cv_index, m_flat ? CellTreeModel::Flat : 0, 0, m_sorting));
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ class HCPCellTreeWidget
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
HCPCellTreeWidget (QWidget *parent, const char *name);
|
||||
HCPCellTreeWidget (QWidget *parent, const char *name, QWidget *key_event_receiver);
|
||||
|
||||
signals:
|
||||
void cell_clicked (const QModelIndex &);
|
||||
|
|
@ -78,8 +78,11 @@ protected:
|
|||
virtual void mousePressEvent (QMouseEvent *event);
|
||||
virtual void mouseReleaseEvent (QMouseEvent *event);
|
||||
virtual void startDrag (Qt::DropActions supportedActions);
|
||||
virtual bool focusNextPrevChild (bool next);
|
||||
virtual void keyPressEvent (QKeyEvent *event);
|
||||
virtual bool event (QEvent *event);
|
||||
|
||||
QWidget *mp_key_event_receiver;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -255,6 +258,14 @@ public:
|
|||
return m_split_mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the layout view this panel is attached to
|
||||
*/
|
||||
lay::LayoutView *view ()
|
||||
{
|
||||
return mp_view;
|
||||
}
|
||||
|
||||
signals:
|
||||
void cell_selected (cell_path_type path, int cellview_index);
|
||||
void active_cellview_changed (int cellview_index);
|
||||
|
|
|
|||
|
|
@ -97,9 +97,6 @@ private:
|
|||
LCPTreeWidget::LCPTreeWidget (QWidget *parent, lay::LayerTreeModel *model, const char *name)
|
||||
: QTreeView (parent), mp_model (model)
|
||||
{
|
||||
// Don't request focus: this leaves focus on the canvas and the arrow keys functional there
|
||||
setFocusPolicy (Qt::NoFocus);
|
||||
|
||||
setObjectName (QString::fromUtf8 (name));
|
||||
setModel (model);
|
||||
setItemDelegate (new LCPItemDelegate (this));
|
||||
|
|
@ -149,7 +146,38 @@ LCPTreeWidget::mouseDoubleClickEvent (QMouseEvent *event)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
LCPTreeWidget::focusNextPrevChild (bool /*next*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
LCPTreeWidget::event (QEvent *event)
|
||||
{
|
||||
// Handling this event makes the widget receive all keystrokes
|
||||
if (event->type () == QEvent::ShortcutOverride) {
|
||||
QKeyEvent *ke = static_cast<QKeyEvent *> (event);
|
||||
QString t = ke->text ();
|
||||
if (!t.isEmpty () && t[0].isPrint ()) {
|
||||
ke->accept ();
|
||||
}
|
||||
}
|
||||
return QTreeView::event (event);
|
||||
}
|
||||
|
||||
void
|
||||
LCPTreeWidget::keyPressEvent (QKeyEvent *event)
|
||||
{
|
||||
QString t = event->text ();
|
||||
if (!t.isEmpty () && t[0].isPrint ()) {
|
||||
emit search_triggered (t);
|
||||
} else {
|
||||
QTreeView::keyPressEvent (event);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LCPTreeWidget::collapse_all ()
|
||||
{
|
||||
#if QT_VERSION >= 0x040200
|
||||
|
|
@ -299,6 +327,70 @@ LayerControlPanel::LayerControlPanel (lay::LayoutView *view, db::Manager *manage
|
|||
l->setMargin (0);
|
||||
l->setSpacing (0);
|
||||
|
||||
mp_search_frame = new QFrame (this);
|
||||
l->addWidget (mp_search_frame);
|
||||
mp_search_frame->hide ();
|
||||
mp_search_frame->setAutoFillBackground (true);
|
||||
mp_search_frame->setObjectName (QString::fromUtf8 ("panel"));
|
||||
mp_search_frame->setFrameStyle (QFrame::Panel | QFrame::Raised);
|
||||
mp_search_frame->setLineWidth (1);
|
||||
mp_search_frame->setBackgroundRole (QPalette::Highlight);
|
||||
|
||||
QHBoxLayout *sf_ly = new QHBoxLayout (mp_search_frame);
|
||||
sf_ly->setMargin (0);
|
||||
sf_ly->setContentsMargins (0, 0, 0, 0);
|
||||
sf_ly->setSpacing (0);
|
||||
|
||||
mp_search_close_cb = new QCheckBox (mp_search_frame);
|
||||
sf_ly->addWidget (mp_search_close_cb);
|
||||
|
||||
mp_search_close_cb->setFocusPolicy (Qt::NoFocus);
|
||||
mp_search_close_cb->setBackgroundRole (QPalette::Highlight);
|
||||
mp_search_close_cb->setSizePolicy (QSizePolicy (QSizePolicy::Fixed, QSizePolicy::Preferred));
|
||||
QPalette pl (mp_search_close_cb->palette ());
|
||||
pl.setColor (QPalette::Foreground, pl.color (QPalette::Active, QPalette::HighlightedText));
|
||||
mp_search_close_cb->setPalette (pl);
|
||||
mp_search_close_cb->setMaximumSize (QSize (mp_search_close_cb->maximumSize ().width (), mp_search_close_cb->sizeHint ().height () - 4));
|
||||
connect (mp_search_close_cb, SIGNAL (clicked ()), this, SLOT (search_editing_finished ()));
|
||||
|
||||
mp_search_edit_box = new lay::DecoratedLineEdit (mp_search_frame);
|
||||
mp_search_edit_box->setObjectName (QString::fromUtf8 ("cellview_search_edit_box"));
|
||||
mp_search_edit_box->set_escape_signal_enabled (true);
|
||||
mp_search_edit_box->set_tab_signal_enabled (true);
|
||||
connect (mp_search_edit_box, SIGNAL (returnPressed ()), this, SLOT (search_editing_finished ()));
|
||||
connect (mp_search_edit_box, SIGNAL (textEdited (const QString &)), this, SLOT (search_edited ()));
|
||||
connect (mp_search_edit_box, SIGNAL (esc_pressed ()), this, SLOT (search_editing_finished ()));
|
||||
connect (mp_search_edit_box, SIGNAL (tab_pressed ()), this, SLOT (search_next ()));
|
||||
connect (mp_search_edit_box, SIGNAL (backtab_pressed ()), this, SLOT (search_prev ()));
|
||||
sf_ly->addWidget (mp_search_edit_box);
|
||||
|
||||
mp_use_regular_expressions = new QAction (this);
|
||||
mp_use_regular_expressions->setCheckable (true);
|
||||
mp_use_regular_expressions->setChecked (true);
|
||||
mp_use_regular_expressions->setText (tr ("Use expressions (use * and ? for any character)"));
|
||||
|
||||
mp_case_sensitive = new QAction (this);
|
||||
mp_case_sensitive->setCheckable (true);
|
||||
mp_case_sensitive->setChecked (true);
|
||||
mp_case_sensitive->setText (tr ("Case sensitive search"));
|
||||
|
||||
QMenu *m = new QMenu (mp_search_edit_box);
|
||||
m->addAction (mp_use_regular_expressions);
|
||||
m->addAction (mp_case_sensitive);
|
||||
connect (mp_use_regular_expressions, SIGNAL (triggered ()), this, SLOT (search_edited ()));
|
||||
connect (mp_case_sensitive, SIGNAL (triggered ()), this, SLOT (search_edited ()));
|
||||
|
||||
mp_search_edit_box->set_clear_button_enabled (true);
|
||||
mp_search_edit_box->set_options_button_enabled (true);
|
||||
mp_search_edit_box->set_options_menu (m);
|
||||
|
||||
QToolButton *sf_next = new QToolButton (mp_search_frame);
|
||||
sf_next->setAutoRaise (true);
|
||||
sf_next->setToolTip (tr ("Find next"));
|
||||
sf_next->setIcon (QIcon (QString::fromUtf8 (":/find.png")));
|
||||
connect (sf_next, SIGNAL (clicked ()), this, SLOT (search_next ()));
|
||||
sf_ly->addWidget (sf_next);
|
||||
|
||||
mp_tab_bar = new QTabBar (this);
|
||||
mp_tab_bar->setObjectName (QString::fromUtf8 ("lcp_tabs"));
|
||||
connect (mp_tab_bar, SIGNAL (currentChanged (int)), this, SLOT (tab_selected (int)));
|
||||
|
|
@ -321,6 +413,7 @@ LayerControlPanel::LayerControlPanel (lay::LayoutView *view, db::Manager *manage
|
|||
connect (mp_layer_list, SIGNAL (double_clicked (const QModelIndex &, Qt::KeyboardModifiers)), this, SLOT (double_clicked (const QModelIndex &, Qt::KeyboardModifiers)));
|
||||
connect (mp_layer_list, SIGNAL (collapsed (const QModelIndex &)), this, SLOT (group_collapsed (const QModelIndex &)));
|
||||
connect (mp_layer_list, SIGNAL (expanded (const QModelIndex &)), this, SLOT (group_expanded (const QModelIndex &)));
|
||||
connect (mp_layer_list, SIGNAL (search_triggered (const QString &)), this, SLOT (search_triggered (const QString &)));
|
||||
mp_layer_list->setContextMenuPolicy (Qt::CustomContextMenu);
|
||||
connect (mp_layer_list, SIGNAL(customContextMenuRequested (const QPoint &)), this, SLOT (context_menu (const QPoint &)));
|
||||
mp_layer_list->header ()->hide ();
|
||||
|
|
@ -1130,6 +1223,77 @@ LayerControlPanel::clear_selection ()
|
|||
set_selection (empty_sel);
|
||||
}
|
||||
|
||||
void
|
||||
LayerControlPanel::search_triggered (const QString &t)
|
||||
{
|
||||
if (mp_model) {
|
||||
mp_search_close_cb->setChecked (true);
|
||||
mp_search_frame->show ();
|
||||
mp_search_edit_box->setText (t);
|
||||
mp_search_edit_box->setFocus ();
|
||||
search_edited ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LayerControlPanel::search_edited ()
|
||||
{
|
||||
if (! mp_model) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString t = mp_search_edit_box->text ();
|
||||
if (t.isEmpty ()) {
|
||||
mp_model->clear_locate ();
|
||||
mp_layer_list->setCurrentIndex (QModelIndex ());
|
||||
} else {
|
||||
QModelIndex found = mp_model->locate (t.toUtf8 ().constData (), mp_use_regular_expressions->isChecked (), mp_case_sensitive->isChecked (), false);
|
||||
mp_layer_list->setCurrentIndex (found);
|
||||
if (found.isValid ()) {
|
||||
mp_layer_list->scrollTo (found);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LayerControlPanel::search_next ()
|
||||
{
|
||||
if (! mp_model) {
|
||||
return;
|
||||
}
|
||||
|
||||
QModelIndex found = mp_model->locate_next ();
|
||||
if (found.isValid ()) {
|
||||
mp_layer_list->setCurrentIndex (found);
|
||||
mp_layer_list->scrollTo (found);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LayerControlPanel::search_prev ()
|
||||
{
|
||||
if (! mp_model) {
|
||||
return;
|
||||
}
|
||||
|
||||
QModelIndex found = mp_model->locate_prev ();
|
||||
if (found.isValid ()) {
|
||||
mp_layer_list->setCurrentIndex (found);
|
||||
mp_layer_list->scrollTo (found);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LayerControlPanel::search_editing_finished ()
|
||||
{
|
||||
if (! mp_model) {
|
||||
return;
|
||||
}
|
||||
|
||||
mp_model->clear_locate ();
|
||||
mp_search_frame->hide ();
|
||||
}
|
||||
|
||||
void
|
||||
LayerControlPanel::cm_regroup_flatten ()
|
||||
{
|
||||
|
|
@ -1727,6 +1891,10 @@ set_hidden_flags_rec (LayerTreeModel *model, QTreeView *tree_view, const QModelI
|
|||
void
|
||||
LayerControlPanel::do_update_content ()
|
||||
{
|
||||
// clear search. TODO: update search instead of clearing
|
||||
mp_search_edit_box->clear ();
|
||||
mp_model->clear_locate();
|
||||
|
||||
mp_model->set_phase (m_phase);
|
||||
|
||||
if (m_tabs_need_update) {
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@
|
|||
#include "layDitherPattern.h"
|
||||
#include "layLayerProperties.h"
|
||||
#include "layLayerTreeModel.h"
|
||||
#include "layWidgets.h"
|
||||
#include "dbObject.h"
|
||||
#include "tlDeferredExecution.h"
|
||||
|
||||
|
|
@ -52,6 +53,7 @@ class QModelIndex;
|
|||
class QMenu;
|
||||
class QLabel;
|
||||
class QTabBar;
|
||||
class QCheckBox;
|
||||
|
||||
namespace lay
|
||||
{
|
||||
|
|
@ -85,6 +87,12 @@ public:
|
|||
|
||||
signals:
|
||||
void double_clicked (const QModelIndex &, Qt::KeyboardModifiers);
|
||||
void search_triggered (const QString &t);
|
||||
|
||||
protected:
|
||||
virtual void keyPressEvent (QKeyEvent *event);
|
||||
virtual bool event (QEvent *event);
|
||||
virtual bool focusNextPrevChild (bool next);
|
||||
|
||||
private:
|
||||
lay::LayerTreeModel *mp_model;
|
||||
|
|
@ -322,6 +330,11 @@ public slots:
|
|||
void upup_clicked ();
|
||||
void down_clicked ();
|
||||
void downdown_clicked ();
|
||||
void search_triggered (const QString &t);
|
||||
void search_edited ();
|
||||
void search_editing_finished ();
|
||||
void search_next ();
|
||||
void search_prev ();
|
||||
|
||||
private:
|
||||
QTabBar *mp_tab_bar;
|
||||
|
|
@ -341,6 +354,11 @@ private:
|
|||
std::set<unsigned int> m_expanded;
|
||||
bool m_no_stipples;
|
||||
QLabel *m_no_stipples_label;
|
||||
lay::DecoratedLineEdit *mp_search_edit_box;
|
||||
QAction *mp_case_sensitive;
|
||||
QAction *mp_use_regular_expressions;
|
||||
QFrame *mp_search_frame;
|
||||
QCheckBox *mp_search_close_cb;
|
||||
|
||||
void clear_selection ();
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include "dbLayoutUtils.h"
|
||||
#include "tlLog.h"
|
||||
#include "tlTimer.h"
|
||||
#include "tlGlobPattern.h"
|
||||
|
||||
#include <QTreeView>
|
||||
#include <QModelIndex>
|
||||
|
|
@ -278,6 +279,92 @@ LayerTreeModel::index (int row, int column, const QModelIndex &parent) const
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
LayerTreeModel::clear_locate ()
|
||||
{
|
||||
m_selected_indexes.clear ();
|
||||
m_current_index = m_selected_indexes.begin ();
|
||||
m_selected_ids.clear ();
|
||||
|
||||
signal_data_changed ();
|
||||
}
|
||||
|
||||
QModelIndex
|
||||
LayerTreeModel::locate_next ()
|
||||
{
|
||||
if (m_current_index == m_selected_indexes.end ()) {
|
||||
return QModelIndex ();
|
||||
} else {
|
||||
++m_current_index;
|
||||
if (m_current_index == m_selected_indexes.end ()) {
|
||||
m_current_index = m_selected_indexes.begin ();
|
||||
}
|
||||
return *m_current_index;
|
||||
}
|
||||
}
|
||||
|
||||
QModelIndex
|
||||
LayerTreeModel::locate_prev ()
|
||||
{
|
||||
if (m_current_index == m_selected_indexes.end ()) {
|
||||
return QModelIndex ();
|
||||
} else {
|
||||
if (m_current_index == m_selected_indexes.begin ()) {
|
||||
m_current_index = m_selected_indexes.end ();
|
||||
}
|
||||
--m_current_index;
|
||||
return *m_current_index;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LayerTreeModel::search_children (const tl::GlobPattern &pattern, const QModelIndex &parent, bool recurse)
|
||||
{
|
||||
int children = rowCount (parent);
|
||||
for (int i = 0; i < children; ++i) {
|
||||
|
||||
QModelIndex child = index (i, 0, parent);
|
||||
|
||||
lay::LayerPropertiesConstIterator iter (iterator (child));
|
||||
if (!iter.is_null () && !iter.at_end () &&
|
||||
pattern.match (iter->display_string (mp_view, true /*real*/))) {
|
||||
m_selected_indexes.push_back (child);
|
||||
}
|
||||
|
||||
if (recurse && iter->has_children ()) {
|
||||
search_children (pattern, child, recurse);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
QModelIndex
|
||||
LayerTreeModel::locate (const char *name, bool glob_pattern, bool case_sensitive, bool top_only)
|
||||
{
|
||||
m_selected_indexes.clear ();
|
||||
|
||||
tl::GlobPattern p = tl::GlobPattern (std::string (name));
|
||||
p.set_case_sensitive (case_sensitive);
|
||||
p.set_exact (!glob_pattern);
|
||||
p.set_header_match (true);
|
||||
|
||||
search_children (p, QModelIndex (), !top_only);
|
||||
|
||||
m_selected_ids.clear ();
|
||||
for (std::vector<QModelIndex>::const_iterator i = m_selected_indexes.begin (); i != m_selected_indexes.end (); ++i) {
|
||||
m_selected_ids.insert (size_t (i->internalPointer ()));
|
||||
}
|
||||
|
||||
signal_data_changed ();
|
||||
|
||||
m_current_index = m_selected_indexes.begin ();
|
||||
if (m_current_index == m_selected_indexes.end ()) {
|
||||
return QModelIndex ();
|
||||
} else {
|
||||
return *m_current_index;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LayerTreeModel::signal_data_changed ()
|
||||
{
|
||||
|
|
@ -648,6 +735,18 @@ LayerTreeModel::data (const QModelIndex &index, int role) const
|
|||
|
||||
}
|
||||
|
||||
} else if (role == Qt::BackgroundRole) {
|
||||
|
||||
if (m_selected_ids.find (size_t (index.internalPointer ())) != m_selected_ids.end ()) {
|
||||
// for selected items pick a color between Highlight and Base
|
||||
QPalette pl (mp_view->palette ());
|
||||
QColor c1 = pl.color (QPalette::Highlight);
|
||||
QColor cb = pl.color (QPalette::Base);
|
||||
return QVariant (QColor ((c1.red () + cb.red ()) / 2, (c1.green () + cb.green ()) / 2, (c1.blue () + cb.blue ()) / 2));
|
||||
} else {
|
||||
return QVariant ();
|
||||
}
|
||||
|
||||
} else if (role == Qt::TextColorRole || role == Qt::FontRole) {
|
||||
|
||||
if (index.column () == 1) {
|
||||
|
|
|
|||
|
|
@ -38,6 +38,11 @@ namespace db
|
|||
class Layout;
|
||||
}
|
||||
|
||||
namespace tl
|
||||
{
|
||||
class GlobPattern;
|
||||
}
|
||||
|
||||
namespace lay
|
||||
{
|
||||
|
||||
|
|
@ -161,6 +166,29 @@ public:
|
|||
*/
|
||||
void signal_data_changed ();
|
||||
|
||||
/**
|
||||
* @brief Locate an index by name (at least closest)
|
||||
*
|
||||
* If top_only is set, only top-level items are searched. An invalid model index is returned if
|
||||
* no corresponding item could be found.
|
||||
*/
|
||||
QModelIndex locate (const char *name, bool glob_pattern = false, bool case_sensitive = true, bool top_only = true);
|
||||
|
||||
/**
|
||||
* @brief Locate the next index (after the first locate)
|
||||
*/
|
||||
QModelIndex locate_next ();
|
||||
|
||||
/**
|
||||
* @brief Locate the previous index (after the first locate)
|
||||
*/
|
||||
QModelIndex locate_prev ();
|
||||
|
||||
/**
|
||||
* @brief Clears the locate flags
|
||||
*/
|
||||
void clear_locate ();
|
||||
|
||||
/**
|
||||
* @brief Set the test_shapes_in_view flag
|
||||
*
|
||||
|
|
@ -194,6 +222,11 @@ private:
|
|||
QFont m_font;
|
||||
QColor m_text_color, m_background_color;
|
||||
mutable EmptyWithinViewCache m_test_shapes_cache;
|
||||
std::set <size_t> m_selected_ids;
|
||||
std::vector <QModelIndex> m_selected_indexes;
|
||||
std::vector <QModelIndex>::const_iterator m_current_index;
|
||||
|
||||
void search_children (const tl::GlobPattern &pattern, const QModelIndex &parent, bool recurse);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@
|
|||
#include "tlString.h"
|
||||
#include "tlLog.h"
|
||||
#include "tlAssert.h"
|
||||
#include "layLayoutView.h"
|
||||
#include "layViewOp.h"
|
||||
#include "layViewObject.h"
|
||||
#include "layLayoutViewConfigPages.h"
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include <QWheelEvent>
|
||||
#include <QKeyEvent>
|
||||
#include <QMimeData>
|
||||
#include <QCoreApplication>
|
||||
|
||||
#include "layViewObject.h"
|
||||
#include "layCanvasPlane.h"
|
||||
|
|
@ -367,6 +368,12 @@ ViewObjectWidget::end_mouse_event ()
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ViewObjectWidget::focusNextPrevChild (bool /*next*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
ViewObjectWidget::keyPressEvent (QKeyEvent *e)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -603,66 +603,6 @@ public:
|
|||
*/
|
||||
~ViewObjectWidget ();
|
||||
|
||||
/**
|
||||
* @brief Qt keyboard event handler
|
||||
*/
|
||||
void keyPressEvent (QKeyEvent *e);
|
||||
|
||||
/**
|
||||
* @brief Qt mouse move event handler
|
||||
*/
|
||||
void mouseMoveEvent (QMouseEvent *e);
|
||||
|
||||
/**
|
||||
* @brief Qt mouse leave event handler
|
||||
*/
|
||||
void leaveEvent (QEvent *e);
|
||||
|
||||
/**
|
||||
* @brief Qt mouse enter event handler
|
||||
*/
|
||||
void enterEvent (QEvent *e);
|
||||
|
||||
/**
|
||||
* @brief Qt mouse button press event handler
|
||||
*/
|
||||
void mousePressEvent (QMouseEvent *e);
|
||||
|
||||
/**
|
||||
* @brief Qt mouse button double-click event handler
|
||||
*/
|
||||
void mouseDoubleClickEvent (QMouseEvent *e);
|
||||
|
||||
/**
|
||||
* @brief Qt mouse button release event handler
|
||||
*/
|
||||
void mouseReleaseEvent (QMouseEvent *e);
|
||||
|
||||
/**
|
||||
* @brief Qt drag enter event handler
|
||||
*/
|
||||
void dragEnterEvent (QDragEnterEvent *event);
|
||||
|
||||
/**
|
||||
* @brief Qt drag leave event handler
|
||||
*/
|
||||
void dragLeaveEvent (QDragLeaveEvent *event);
|
||||
|
||||
/**
|
||||
* @brief Qt drag enter event handler
|
||||
*/
|
||||
void dragMoveEvent (QDragMoveEvent *event);
|
||||
|
||||
/**
|
||||
* @brief Qt drop event handler
|
||||
*/
|
||||
void dropEvent (QDropEvent *event);
|
||||
|
||||
/**
|
||||
* @brief Qt mouse wheel event handler
|
||||
*/
|
||||
void wheelEvent (QWheelEvent *e);
|
||||
|
||||
/**
|
||||
* @brief Cancel all drag operations
|
||||
*/
|
||||
|
|
@ -966,6 +906,71 @@ public:
|
|||
void set_default_cursor (lay::Cursor::cursor_shape cursor);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Qt focus event handler
|
||||
*/
|
||||
bool focusNextPrevChild (bool next);
|
||||
|
||||
/**
|
||||
* @brief Qt keyboard event handler
|
||||
*/
|
||||
void keyPressEvent (QKeyEvent *e);
|
||||
|
||||
/**
|
||||
* @brief Qt mouse move event handler
|
||||
*/
|
||||
void mouseMoveEvent (QMouseEvent *e);
|
||||
|
||||
/**
|
||||
* @brief Qt mouse leave event handler
|
||||
*/
|
||||
void leaveEvent (QEvent *e);
|
||||
|
||||
/**
|
||||
* @brief Qt mouse enter event handler
|
||||
*/
|
||||
void enterEvent (QEvent *e);
|
||||
|
||||
/**
|
||||
* @brief Qt mouse button press event handler
|
||||
*/
|
||||
void mousePressEvent (QMouseEvent *e);
|
||||
|
||||
/**
|
||||
* @brief Qt mouse button double-click event handler
|
||||
*/
|
||||
void mouseDoubleClickEvent (QMouseEvent *e);
|
||||
|
||||
/**
|
||||
* @brief Qt mouse button release event handler
|
||||
*/
|
||||
void mouseReleaseEvent (QMouseEvent *e);
|
||||
|
||||
/**
|
||||
* @brief Qt drag enter event handler
|
||||
*/
|
||||
void dragEnterEvent (QDragEnterEvent *event);
|
||||
|
||||
/**
|
||||
* @brief Qt drag leave event handler
|
||||
*/
|
||||
void dragLeaveEvent (QDragLeaveEvent *event);
|
||||
|
||||
/**
|
||||
* @brief Qt drag enter event handler
|
||||
*/
|
||||
void dragMoveEvent (QDragMoveEvent *event);
|
||||
|
||||
/**
|
||||
* @brief Qt drop event handler
|
||||
*/
|
||||
void dropEvent (QDropEvent *event);
|
||||
|
||||
/**
|
||||
* @brief Qt mouse wheel event handler
|
||||
*/
|
||||
void wheelEvent (QWheelEvent *e);
|
||||
|
||||
/**
|
||||
* @brief Set the transformation for mouse events
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -976,6 +976,8 @@ bool DecoratedLineEdit::event (QEvent *event)
|
|||
QKeyEvent *ke = static_cast<QKeyEvent *> (event);
|
||||
if (ke->key () == Qt::Key_Escape && m_escape_signal_enabled) {
|
||||
ke->accept ();
|
||||
} else if ((ke->key () == Qt::Key_Tab || ke->key () == Qt::Key_Backtab) && m_tab_signal_enabled) {
|
||||
ke->accept ();
|
||||
}
|
||||
}
|
||||
return QLineEdit::event (event);
|
||||
|
|
|
|||
Loading…
Reference in New Issue