1 | // Copyright (C) 2016 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 |
3 | |
4 | #include "openpagesswitcher.h" |
5 | |
6 | #include "centralwidget.h" |
7 | #include "openpagesmodel.h" |
8 | #include "openpageswidget.h" |
9 | #include "tracer.h" |
10 | |
11 | #include <QtCore/QEvent> |
12 | |
13 | #include <QtGui/QKeyEvent> |
14 | #include <QtWidgets/QVBoxLayout> |
15 | |
16 | QT_BEGIN_NAMESPACE |
17 | |
18 | const int gWidth = 300; |
19 | const int gHeight = 200; |
20 | |
21 | OpenPagesSwitcher::OpenPagesSwitcher(OpenPagesModel *model) |
22 | : QFrame(nullptr, Qt::Popup) |
23 | , m_openPagesModel(model) |
24 | { |
25 | TRACE_OBJ |
26 | resize(w: gWidth, h: gHeight); |
27 | |
28 | m_openPagesWidget = new OpenPagesWidget(m_openPagesModel); |
29 | |
30 | // We disable the frame on this list view and use a QFrame around it instead. |
31 | // This improves the look with QGTKStyle. |
32 | #ifndef Q_OS_MAC |
33 | setFrameStyle(m_openPagesWidget->frameStyle()); |
34 | #endif |
35 | m_openPagesWidget->setFrameStyle(QFrame::NoFrame); |
36 | |
37 | m_openPagesWidget->allowContextMenu(ok: false); |
38 | m_openPagesWidget->installEventFilter(filterObj: this); |
39 | |
40 | QVBoxLayout *layout = new QVBoxLayout(this); |
41 | layout->setContentsMargins(QMargins()); |
42 | layout->addWidget(m_openPagesWidget); |
43 | |
44 | connect(sender: m_openPagesWidget, signal: &OpenPagesWidget::closePage, |
45 | context: this, slot: &OpenPagesSwitcher::closePage); |
46 | connect(sender: m_openPagesWidget, signal: &OpenPagesWidget::setCurrentPage, |
47 | context: this, slot: &OpenPagesSwitcher::setCurrentPage); |
48 | } |
49 | |
50 | OpenPagesSwitcher::~OpenPagesSwitcher() |
51 | { |
52 | TRACE_OBJ |
53 | } |
54 | |
55 | void OpenPagesSwitcher::gotoNextPage() |
56 | { |
57 | TRACE_OBJ |
58 | selectPageUpDown(summand: 1); |
59 | } |
60 | |
61 | void OpenPagesSwitcher::gotoPreviousPage() |
62 | { |
63 | TRACE_OBJ |
64 | selectPageUpDown(summand: -1); |
65 | } |
66 | |
67 | void OpenPagesSwitcher::selectAndHide() |
68 | { |
69 | TRACE_OBJ |
70 | setVisible(false); |
71 | emit setCurrentPage(m_openPagesWidget->currentIndex()); |
72 | } |
73 | |
74 | void OpenPagesSwitcher::selectCurrentPage() |
75 | { |
76 | TRACE_OBJ |
77 | m_openPagesWidget->selectCurrentPage(); |
78 | } |
79 | |
80 | void OpenPagesSwitcher::setVisible(bool visible) |
81 | { |
82 | TRACE_OBJ |
83 | QWidget::setVisible(visible); |
84 | if (visible) |
85 | setFocus(); |
86 | } |
87 | |
88 | void OpenPagesSwitcher::focusInEvent(QFocusEvent *event) |
89 | { |
90 | TRACE_OBJ |
91 | Q_UNUSED(event); |
92 | m_openPagesWidget->setFocus(); |
93 | } |
94 | |
95 | bool OpenPagesSwitcher::eventFilter(QObject *object, QEvent *event) |
96 | { |
97 | TRACE_OBJ |
98 | if (object == m_openPagesWidget) { |
99 | if (event->type() == QEvent::KeyPress) { |
100 | QKeyEvent *ke = static_cast<QKeyEvent*>(event); |
101 | if (ke->key() == Qt::Key_Escape) { |
102 | setVisible(false); |
103 | return true; |
104 | } |
105 | |
106 | const int key = ke->key(); |
107 | if (key == Qt::Key_Return || key == Qt::Key_Enter || key == Qt::Key_Space) { |
108 | emit setCurrentPage(m_openPagesWidget->currentIndex()); |
109 | return true; |
110 | } |
111 | |
112 | Qt::KeyboardModifier modifier = Qt::ControlModifier; |
113 | #ifdef Q_OS_MAC |
114 | modifier = Qt::AltModifier; |
115 | #endif |
116 | if (key == Qt::Key_Backtab |
117 | && (ke->modifiers() == (modifier | Qt::ShiftModifier))) |
118 | gotoPreviousPage(); |
119 | else if (key == Qt::Key_Tab && (ke->modifiers() == modifier)) |
120 | gotoNextPage(); |
121 | } else if (event->type() == QEvent::KeyRelease) { |
122 | QKeyEvent *ke = static_cast<QKeyEvent*>(event); |
123 | if (ke->modifiers() == 0 |
124 | /*HACK this is to overcome some event inconsistencies between platforms*/ |
125 | || (ke->modifiers() == Qt::AltModifier |
126 | && (ke->key() == Qt::Key_Alt || ke->key() == -1))) { |
127 | selectAndHide(); |
128 | } |
129 | } |
130 | } |
131 | return QWidget::eventFilter(watched: object, event); |
132 | } |
133 | |
134 | void OpenPagesSwitcher::selectPageUpDown(int summand) |
135 | { |
136 | TRACE_OBJ |
137 | const int pageCount = m_openPagesModel->rowCount(); |
138 | if (pageCount < 2) |
139 | return; |
140 | |
141 | const QModelIndexList &list = m_openPagesWidget->selectionModel()->selectedIndexes(); |
142 | if (list.isEmpty()) |
143 | return; |
144 | |
145 | QModelIndex index = list.first(); |
146 | if (!index.isValid()) |
147 | return; |
148 | |
149 | index = m_openPagesModel->index(row: (index.row() + summand + pageCount) % pageCount, column: 0); |
150 | if (index.isValid()) { |
151 | m_openPagesWidget->setCurrentIndex(index); |
152 | m_openPagesWidget->scrollTo(index, hint: QAbstractItemView::PositionAtCenter); |
153 | } |
154 | } |
155 | |
156 | QT_END_NAMESPACE |
157 | |