1 | /* |
2 | SPDX-FileCopyrightText: 2019-2020 Nibaldo González S. <nibgonz@gmail.com> |
3 | |
4 | SPDX-License-Identifier: LGPL-2.0-or-later |
5 | */ |
6 | |
7 | /* |
8 | * NOTE: The KateModeMenuListData::SearchLine class is based on |
9 | * KListWidgetSearchLine, by Scott Wheeler <wheeler@kde.org> and |
10 | * Gustavo Sverzut Barbieri <gsbarbieri@users.sourceforge.net>. |
11 | * See: https://api.kde.org/frameworks/kitemviews/html/classKListWidgetSearchLine.html |
12 | * |
13 | * TODO: Add keyboard shortcut to show the menu. |
14 | * See: KateModeMenuList::showEvent() |
15 | */ |
16 | |
17 | #ifndef KATEMODEMENULIST_H |
18 | #define |
19 | |
20 | #include <QGridLayout> |
21 | #include <QIcon> |
22 | #include <QKeyEvent> |
23 | #include <QLabel> |
24 | #include <QLineEdit> |
25 | #include <QListView> |
26 | #include <QMenu> |
27 | #include <QPointer> |
28 | #include <QPushButton> |
29 | #include <QScrollBar> |
30 | #include <QStandardItemModel> |
31 | #include <QString> |
32 | |
33 | namespace KTextEditor |
34 | { |
35 | class DocumentPrivate; |
36 | class Document; |
37 | } |
38 | |
39 | namespace KateModeMenuListData |
40 | { |
41 | class ListView; |
42 | class ListItem; |
43 | class SearchLine; |
44 | class Factory; |
45 | } |
46 | |
47 | class KateFileType; |
48 | /** |
49 | * Class of menu to select the |
50 | * syntax highlighting language (mode menu). |
51 | * Provides a menu with a scrollable list plus search bar. |
52 | * |
53 | * This is an alternative to the classic mode menu of the KateModeMenu class. |
54 | * |
55 | * @see KateModeManager, KateFileType, KateModeMenu |
56 | */ |
57 | class : public QMenu |
58 | { |
59 | public: |
60 | /** |
61 | * Horizontal Alignment with respect to the trigger button. |
62 | * "AlignHDefault" is the normal alignment. |
63 | * "AlignHInverse" uses right alignment in Left-to-right layouts and |
64 | * left alignmentnin Right-to-left layouts (used in some languages). |
65 | * "AlignLeft" and "AlignRight" forces the alignment, regardless of the layout direction. |
66 | * @see setButton(), QWidget::layoutDirection(), Qt::LayoutDirection |
67 | */ |
68 | enum { |
69 | , |
70 | , |
71 | , |
72 | |
73 | }; |
74 | /** |
75 | * Vertical Alignment with respect to the trigger button. |
76 | * "AlignVDefault" uses normal alignment (below the button) and "AlignTop" |
77 | * forces the alignment above the trigger button. |
78 | * @see setButton(), KateStatusBarOpenUpMenu::setVisible() |
79 | */ |
80 | enum { |
81 | , |
82 | |
83 | }; |
84 | /** |
85 | * Define if the trigger button label must be updated when selecting an item. |
86 | * @see setButton() |
87 | */ |
88 | enum class : bool; |
89 | /** |
90 | * Search bar position, above or below the list. |
91 | */ |
92 | enum { |
93 | , |
94 | |
95 | }; |
96 | /** |
97 | * Defines where the list will scroll after clearing the search or changing the view. |
98 | * @see setAutoScroll(), autoScroll() |
99 | */ |
100 | enum { |
101 | , |
102 | |
103 | }; |
104 | |
105 | (const QString &title, QWidget *parent) |
106 | : QMenu(title, parent) |
107 | { |
108 | init(); |
109 | } |
110 | |
111 | /** |
112 | * Reload all items. |
113 | * @see KateModeManager::update() |
114 | */ |
115 | void (); |
116 | |
117 | /** |
118 | * Update the selected item in the list widget, but without changing |
119 | * the syntax highlighting in the document. |
120 | * This is useful for updating this menu, when changing the syntax highlighting |
121 | * from another menu, or from an external one. This doesn't hide or show the menu. |
122 | * @param nameMode Raw name of the syntax highlight definition. If it's empty, |
123 | * the "Normal" mode will be used. |
124 | * @return True if @p nameMode exists and is selected. |
125 | */ |
126 | bool (const QString &nameMode); |
127 | /** |
128 | * Update the selected item in the list widget, but without changing |
129 | * the syntax highlighting in the document. This doesn't hide or show the menu. |
130 | * The menu is kept updated according to the active syntax highlighting, |
131 | * obtained from the KTextEditor::DocumentPrivate class. |
132 | * @return True if the item is selected correctly. |
133 | * @see KTextEditor::DocumentPrivate::fileType() |
134 | */ |
135 | bool (); |
136 | |
137 | /** |
138 | * Set the button that shows this menu. It allows to update the label |
139 | * of the button and define the alignment of the menu with respect to it. |
140 | * This function doesn't call QPushButton::setMenu(). |
141 | * @param button Trigger button. |
142 | * @param positionX Horizontal position of the menu with respect to the trigger button. |
143 | * @param positionY Vertical position of the menu with respect to the trigger button. |
144 | * @param autoUpdateTextButton Determines whether the text of the button should be |
145 | * changed when selecting an item from the menu. |
146 | * |
147 | * @see AlignmentHButton, AlignmentVButton, AutoUpdateTextButton |
148 | */ |
149 | void (QPushButton *button, |
150 | AlignmentHButton positionX = AlignHDefault, |
151 | AlignmentVButton positionY = AlignTop, |
152 | AutoUpdateTextButton autoUpdateTextButton = AutoUpdateTextButton(false)); |
153 | |
154 | /** |
155 | * Define the scroll when cleaning the search or changing the view. |
156 | * The default value is AutoScroll::ScrollToSelectedItem. |
157 | * @see AutoScroll |
158 | */ |
159 | void (AutoScroll scroll) |
160 | { |
161 | m_autoScroll = scroll; |
162 | } |
163 | |
164 | /** |
165 | * Set document to apply the syntax highlighting. |
166 | * @see KTextEditor::DocumentPrivate |
167 | */ |
168 | void (KTextEditor::Document *doc); |
169 | |
170 | protected: |
171 | friend KateModeMenuListData::ListView; |
172 | friend KateModeMenuListData::ListItem; |
173 | friend KateModeMenuListData::SearchLine; |
174 | |
175 | /** |
176 | * Action when displaying the menu. |
177 | * Override from QWidget. |
178 | */ |
179 | void (QShowEvent *event) override; |
180 | |
181 | private: |
182 | void (); |
183 | |
184 | void (); |
185 | |
186 | /** |
187 | * Define the size of the list widget, in pixels. The @p width is also |
188 | * applied to the search bar. This does not recalculate the word wrap in items. |
189 | */ |
190 | inline void (const int height, const int width = 266); |
191 | |
192 | /** |
193 | * Load the data model with the syntax highlighting definitions to show in the list. |
194 | */ |
195 | void (); |
196 | |
197 | /** |
198 | * Scroll the list, according to AutoScroll. |
199 | * @see AutoScroll |
200 | */ |
201 | void (); |
202 | |
203 | /** |
204 | * Set a custom word wrap on a text line, according to a maximum width (in pixels). |
205 | * @param text Line of text |
206 | * @param maxWidth Width of the text container, in pixels. |
207 | * @param fontMetrics Font metrics. See QWidget::fontMetrics() |
208 | */ |
209 | QString (const QString &text, const int maxWidth, const QFontMetrics &fontMetrics) const; |
210 | |
211 | /** |
212 | * Update the selected item in the list, with the active syntax highlighting. |
213 | * This method only changes the selected item, with the checkbox icon, doesn't apply |
214 | * syntax highlighting in the document or hides the menu. |
215 | * @see selectHighlighting(), selectHighlightingFromExternal(), selectHighlightingSetVisibility() |
216 | */ |
217 | void (KateModeMenuListData::ListItem *item); |
218 | |
219 | /** |
220 | * Select an item from the list and apply the syntax highlighting in the document. |
221 | * This is equivalent to the slot: KateModeMenuList::selectHighlighting(). |
222 | * @param bHideMenu If the menu should be hidden after applying the highlight. |
223 | * @see selectHighlighting() |
224 | */ |
225 | void selectHighlightingSetVisibility(QStandardItem *pItem, const bool ); |
226 | |
227 | /** |
228 | * Create a new section in the list of items and add it to the model. |
229 | * It corresponds to a separator line and a title. |
230 | * @param sectionName Section title. |
231 | * @param background Background color is generally transparent. |
232 | * @param bSeparator True if a separation line will also be created before the section title. |
233 | * @param modelPosition Position in the model where to insert the new section. If the value is |
234 | * less than zero, the section is added to the end of the list/model. |
235 | * @return A pointer to the item created with the section title. |
236 | */ |
237 | KateModeMenuListData::ListItem *(const QString §ionName, const QBrush &background, bool bSeparator = true, int modelPosition = -1); |
238 | |
239 | /** |
240 | * Load message when the list is empty in the search. |
241 | */ |
242 | void (); |
243 | |
244 | AutoScroll = ScrollToSelectedItem; |
245 | AlignmentHButton ; |
246 | AlignmentVButton ; |
247 | AutoUpdateTextButton ; |
248 | |
249 | QPointer<QPushButton> = nullptr; |
250 | QLabel * = nullptr; |
251 | QGridLayout * = nullptr; |
252 | QScrollBar * = nullptr; |
253 | |
254 | KateModeMenuListData::SearchLine * = nullptr; |
255 | KateModeMenuListData::ListView * = nullptr; |
256 | QStandardItemModel * = nullptr; |
257 | |
258 | /** |
259 | * Item with active syntax highlighting. |
260 | */ |
261 | KateModeMenuListData::ListItem * = nullptr; |
262 | |
263 | /** |
264 | * Icon for selected/active item (checkbox). |
265 | * NOTE: Selected and inactive items show an icon with incorrect color, |
266 | * however, this isn't a problem, since the list widget is never inactive. |
267 | */ |
268 | const QIcon = QIcon::fromTheme(QStringLiteral("checkbox" )); |
269 | QIcon ; |
270 | int = 16; |
271 | |
272 | int ; |
273 | |
274 | QPointer<KTextEditor::DocumentPrivate> ; |
275 | |
276 | bool = false; |
277 | |
278 | private: |
279 | /** |
280 | * Action when selecting a item in the list. This also applies |
281 | * the syntax highlighting in the document and hides the menu. |
282 | * This is equivalent to KateModeMenuList::selectHighlightingSetVisibility(). |
283 | * @see selectHighlightingSetVisibility(), updateSelectedItem() |
284 | */ |
285 | void (const QModelIndex &index); |
286 | }; |
287 | |
288 | namespace KateModeMenuListData |
289 | { |
290 | /** |
291 | * Class of List Widget. |
292 | */ |
293 | class : public QListView |
294 | { |
295 | private: |
296 | (KateModeMenuList *) |
297 | : QListView(menu) |
298 | { |
299 | m_parentMenu = menu; |
300 | } |
301 | |
302 | public: |
303 | () override |
304 | { |
305 | } |
306 | |
307 | /** |
308 | * Define the size of the widget list. |
309 | * @p height and @p width are values in pixels. |
310 | */ |
311 | void (const int height, const int width = 266); |
312 | |
313 | /** |
314 | * Get the width of the list, in pixels. |
315 | * @see QAbstractScrollArea::sizeHint() |
316 | */ |
317 | inline int () const; |
318 | |
319 | /** |
320 | * Get the width of the contents of the list (in pixels), that is, |
321 | * the list minus the scroll bar and margins. |
322 | */ |
323 | int () const; |
324 | |
325 | /** |
326 | * Get the width of the contents of the list (in pixels), that is, the list minus |
327 | * the scroll bar and margins. The parameter allows you to specify additional margins |
328 | * according to the scroll bar, which can be superimposed or fixed depending to the |
329 | * desktop environment or operating system. |
330 | * @param overlayScrollbarMargin Additional margin for the scroll bar, if it is |
331 | * superimposed on the list. |
332 | * @param classicScrollbarMargin Additional margin for the scroll bar, if fixed in the list. |
333 | */ |
334 | inline int (const int overlayScrollbarMargin, const int classicScrollbarMargin) const; |
335 | |
336 | inline void (const int rowItem) |
337 | { |
338 | selectionModel()->setCurrentIndex(index: m_parentMenu->m_model->index(row: rowItem, column: 0), command: QItemSelectionModel::ClearAndSelect); |
339 | } |
340 | |
341 | inline QStandardItem *() const |
342 | { |
343 | return m_parentMenu->m_model->item(row: currentIndex().row(), column: 0); |
344 | } |
345 | |
346 | inline void (const int rowItem, QAbstractItemView::ScrollHint hint = QAbstractItemView::PositionAtCenter) |
347 | { |
348 | scrollTo(index: m_parentMenu->m_model->index(row: rowItem, column: 0), hint); |
349 | } |
350 | |
351 | inline void () |
352 | { |
353 | setCurrentItem(1); |
354 | scrollToTop(); |
355 | } |
356 | |
357 | protected: |
358 | /** |
359 | * Override from QListView. |
360 | */ |
361 | void (QKeyEvent *event) override; |
362 | |
363 | private: |
364 | KateModeMenuList * = nullptr; |
365 | friend Factory; |
366 | }; |
367 | |
368 | /** |
369 | * Class of an Item of the Data Model of the List. |
370 | * @see KateModeMenuListData::ListView, KateFileType, QStandardItemModel |
371 | */ |
372 | class : public QStandardItem |
373 | { |
374 | private: |
375 | () |
376 | : QStandardItem() |
377 | { |
378 | } |
379 | |
380 | const KateFileType * = nullptr; |
381 | QString ; |
382 | |
383 | friend Factory; |
384 | |
385 | public: |
386 | () override |
387 | { |
388 | } |
389 | |
390 | /** |
391 | * Associate this item with a KateFileType object. |
392 | */ |
393 | inline void (KateFileType *type) |
394 | { |
395 | m_type = type; |
396 | } |
397 | const KateFileType *() const |
398 | { |
399 | return m_type; |
400 | } |
401 | bool () const |
402 | { |
403 | return m_type; |
404 | } |
405 | |
406 | /** |
407 | * Generate name of the item used for the search. |
408 | * @param itemName The item name. |
409 | * @return True if a new name is generated for the search. |
410 | */ |
411 | bool (const QString &itemName); |
412 | |
413 | /** |
414 | * Find matches in the extensions of the item mode, with a @p text. |
415 | * @param text Text to match, without dots or asterisks. For example, in |
416 | * a common extension, it corresponds to the text after "*." |
417 | * @return True if a match is found, false if not. |
418 | */ |
419 | bool (const QString &text) const; |
420 | |
421 | const QString &() const |
422 | { |
423 | return m_searchName; |
424 | } |
425 | }; |
426 | |
427 | /** |
428 | * Class of Search Bar. |
429 | * Based on the KListWidgetSearchLine class. |
430 | */ |
431 | class : public QLineEdit |
432 | { |
433 | public: |
434 | () override |
435 | { |
436 | m_bestResults.clear(); |
437 | } |
438 | |
439 | /** |
440 | * Define the width of the search bar, in pixels. |
441 | */ |
442 | void (const int width); |
443 | |
444 | private: |
445 | (KateModeMenuList *) |
446 | : QLineEdit(menu) |
447 | { |
448 | m_parentMenu = menu; |
449 | init(); |
450 | } |
451 | |
452 | void (); |
453 | |
454 | /** |
455 | * Select result of the items search. |
456 | * Used only by KateModeMenuListData::SearchLine::updateSearch(). |
457 | */ |
458 | void (const int rowItem, bool &bEmptySection, int &lastSection, int &firstSection, int &lastItem); |
459 | |
460 | /** |
461 | * Delay in search results after typing, in milliseconds. |
462 | * Default value: 200 |
463 | */ |
464 | static const int = 170; |
465 | |
466 | /** |
467 | * This prevents auto-scrolling when the search is kept clean. |
468 | */ |
469 | bool = false; |
470 | |
471 | QString = QString(); |
472 | int = 0; |
473 | Qt::CaseSensitivity = Qt::CaseInsensitive; |
474 | |
475 | /** |
476 | * List of items to display in the "Best Search Matches" section. The integer value |
477 | * corresponds to the original position of the item in the model. The purpose of this |
478 | * is to restore the position of the items when starting or cleaning a search. |
479 | */ |
480 | QList<QPair<ListItem *, int>> ; |
481 | |
482 | KateModeMenuList * = nullptr; |
483 | friend Factory; |
484 | friend void KateModeMenuList::reloadItems(); |
485 | |
486 | protected: |
487 | /** |
488 | * Override from QLineEdit. This allows you to navigate through |
489 | * the menu and write in the search bar simultaneously with the keyboard. |
490 | */ |
491 | void (QKeyEvent *event) override; |
492 | |
493 | public: |
494 | virtual void (); |
495 | virtual void (const QString &s = QString()); |
496 | |
497 | private: |
498 | void (const QString &s); |
499 | void (); |
500 | }; |
501 | |
502 | class |
503 | { |
504 | private: |
505 | friend KateModeMenuList; |
506 | () { }; |
507 | static ListView *(KateModeMenuList *) |
508 | { |
509 | return new ListView(parentMenu); |
510 | } |
511 | static ListItem *() |
512 | { |
513 | return new ListItem(); |
514 | } |
515 | static SearchLine *(KateModeMenuList *) |
516 | { |
517 | return new SearchLine(parentMenu); |
518 | } |
519 | }; |
520 | } |
521 | |
522 | #endif // KATEMODEMENULIST_H |
523 | |