1 | /* |
2 | * Copyright (C) 2020-2022 Roy Qu (royqh1979@gmail.com) |
3 | * |
4 | * This program is free software: you can redistribute it and/or modify |
5 | * it under the terms of the GNU General Public License as published by |
6 | * the Free Software Foundation, either version 3 of the License, or |
7 | * (at your option) any later version. |
8 | * |
9 | * This program is distributed in the hope that it will be useful, |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | * GNU General Public License for more details. |
13 | * |
14 | * You should have received a copy of the GNU General Public License |
15 | * along with this program. If not, see <https://www.gnu.org/licenses/>. |
16 | */ |
17 | #include "functiontooltipwidget.h" |
18 | |
19 | #include <QHBoxLayout> |
20 | #include <QPushButton> |
21 | |
22 | FunctionTooltipWidget::FunctionTooltipWidget(QWidget *parent) : |
23 | QFrame(parent, Qt::ToolTip | Qt::WindowStaysOnTopHint | Qt::WindowDoesNotAcceptFocus) |
24 | { |
25 | setFocusPolicy(Qt::NoFocus); |
26 | mInfoLabel = new QLabel(this); |
27 | mInfoLabel->setWordWrap(true); |
28 | mInfoLabel->setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed); |
29 | mTotalLabel = new QLabel(this); |
30 | mTotalLabel->setWordWrap(false); |
31 | mTotalLabel->setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Preferred); |
32 | mUpButton = new QToolButton(this); |
33 | mUpButton->setArrowType(Qt::UpArrow); |
34 | mUpButton->setFixedSize(16, 16); |
35 | mUpButton->setAutoRaise(true); |
36 | mDownButton = new QToolButton(this); |
37 | mDownButton->setArrowType(Qt::DownArrow); |
38 | mDownButton->setFixedSize(16, 16); |
39 | mDownButton->setAutoRaise(true); |
40 | |
41 | this->setLayout(new QHBoxLayout()); |
42 | layout()->setContentsMargins(0,0,0,0); |
43 | layout()->setSpacing(0); |
44 | layout()->addWidget(mUpButton); |
45 | layout()->addWidget(mTotalLabel); |
46 | layout()->addWidget(mDownButton); |
47 | layout()->addWidget(mInfoLabel); |
48 | connect(mUpButton,&QPushButton::clicked, |
49 | this,&FunctionTooltipWidget::previousTip); |
50 | connect(mDownButton,&QPushButton::clicked, |
51 | this,&FunctionTooltipWidget::nextTip); |
52 | } |
53 | |
54 | void FunctionTooltipWidget::addTip(const QString &name, const QString& fullname, |
55 | const QString &returnType, const QString &args, const QString &noNameArgs) |
56 | { |
57 | PFunctionInfo info = std::make_shared<FunctionInfo>(); |
58 | info->name = name; |
59 | info->fullname = fullname; |
60 | info->returnType = returnType; |
61 | info->params = splitArgs(args); |
62 | info->nonameParams = splitArgs(noNameArgs); |
63 | mInfos.append(info); |
64 | } |
65 | |
66 | void FunctionTooltipWidget::clearTips() |
67 | { |
68 | mInfos.clear(); |
69 | hide(); |
70 | } |
71 | |
72 | int FunctionTooltipWidget::tipCount() |
73 | { |
74 | return mInfos.count(); |
75 | } |
76 | |
77 | int FunctionTooltipWidget::paramPos() const |
78 | { |
79 | return mParamPos; |
80 | } |
81 | |
82 | void FunctionTooltipWidget::setParamPos(int newParamPos) |
83 | { |
84 | mParamPos = newParamPos; |
85 | } |
86 | |
87 | void FunctionTooltipWidget::nextTip() |
88 | { |
89 | if (mInfoIndex>=mInfos.length()-1) { |
90 | hide(); |
91 | return; |
92 | } |
93 | if (mInfos.length()>0) |
94 | mInfoIndex = std::min(mInfoIndex+1,mInfos.length()-1); |
95 | updateTip(); |
96 | } |
97 | |
98 | void FunctionTooltipWidget::previousTip() |
99 | { |
100 | if (mInfoIndex==0) { |
101 | hide(); |
102 | return ; |
103 | } |
104 | if (mInfos.length()>0) |
105 | mInfoIndex = std::max(mInfoIndex-1,0); |
106 | updateTip(); |
107 | } |
108 | |
109 | void FunctionTooltipWidget::updateTip() |
110 | { |
111 | |
112 | mTotalLabel->setVisible(mInfos.length()>1); |
113 | mUpButton->setVisible(mInfos.length()>1); |
114 | mDownButton->setVisible(mInfos.length()>1); |
115 | mUpButton->setEnabled(mInfoIndex!=0); |
116 | mDownButton->setEnabled(mInfoIndex!=mInfos.length()-1); |
117 | if (mInfos.length()<=0) |
118 | return; |
119 | PFunctionInfo info = mInfos[mInfoIndex]; |
120 | QString text = info->returnType+ " " + info->name; |
121 | if (info->params.length()==0) { |
122 | text += "()" ; |
123 | } else { |
124 | QStringList displayList; |
125 | for (int i=0;i<info->params.length();i++){ |
126 | const QString& param = info->params[i]; |
127 | if (mParamIndex == i) { |
128 | displayList.append(QString("<b>%1</b>" ).arg(param)); |
129 | } else { |
130 | displayList.append(param); |
131 | } |
132 | } |
133 | text += "( " +displayList.join(", " ) + ") " ; |
134 | } |
135 | if (mInfos.length()>1) { |
136 | mTotalLabel->setText(QString("%1/%2" ).arg(mInfoIndex+1).arg(mInfos.length())); |
137 | } |
138 | int width = mInfoLabel->fontMetrics().horizontalAdvance(text); |
139 | if (width > 400) { |
140 | mInfoLabel->setMinimumWidth(410); |
141 | } else { |
142 | mInfoLabel->setMinimumWidth(width); |
143 | } |
144 | mInfoLabel->setText(text); |
145 | } |
146 | |
147 | void FunctionTooltipWidget::guessFunction(int commas) |
148 | { |
149 | if (mInfoIndex>=0 && mInfoIndex<mInfos.count() |
150 | && mInfos[mInfoIndex]->params.count()>commas) |
151 | return; |
152 | for (int i=0;i<mInfos.size();i++) { |
153 | if (mInfos[i]->params.count()>commas) { |
154 | mInfoIndex = i; |
155 | return; |
156 | } |
157 | } |
158 | mInfoIndex = 0; |
159 | return; |
160 | } |
161 | |
162 | QStringList FunctionTooltipWidget::splitArgs(QString argStr) |
163 | { |
164 | int i = 0; |
165 | // Split up argument string by , |
166 | if (argStr.startsWith('(')) { |
167 | i = 1; // assume it starts with ( and ends with ) |
168 | } else { |
169 | i = 0; |
170 | } |
171 | int paramStart = i; |
172 | |
173 | QStringList result; |
174 | while (i < argStr.length()) { |
175 | if ((argStr[i] == ',')) { |
176 | // We've found "int* a" for example |
177 | QString s = argStr.mid(paramStart,i-paramStart); |
178 | result.append(s); |
179 | paramStart = i + 1; // step over , |
180 | } |
181 | i++; |
182 | } |
183 | QString s = argStr.mid(paramStart,i-paramStart); |
184 | s=s.trimmed(); |
185 | if (!s.isEmpty()) { |
186 | if (s.endsWith(')')) |
187 | s.truncate(s.length()-1); |
188 | result.append(s); |
189 | } |
190 | return result; |
191 | } |
192 | |
193 | const QString &FunctionTooltipWidget::functionFullName() const |
194 | { |
195 | return mFunctioFullName; |
196 | } |
197 | |
198 | void FunctionTooltipWidget::setFunctioFullName(const QString &newFunctioFullName) |
199 | { |
200 | mFunctioFullName = newFunctioFullName; |
201 | } |
202 | |
203 | int FunctionTooltipWidget::paramIndex() const |
204 | { |
205 | return mParamIndex; |
206 | } |
207 | |
208 | void FunctionTooltipWidget::setParamIndex(int newParamIndex) |
209 | { |
210 | mParamIndex = newParamIndex; |
211 | updateTip(); |
212 | } |
213 | |
214 | void FunctionTooltipWidget::closeEvent(QCloseEvent *) |
215 | { |
216 | |
217 | } |
218 | |
219 | void FunctionTooltipWidget::showEvent(QShowEvent *) |
220 | { |
221 | if (mInfoIndex<0 || mInfoIndex>= mInfos.count()) { |
222 | mInfoIndex = 0; |
223 | } |
224 | updateTip(); |
225 | } |
226 | |
227 | void FunctionTooltipWidget::hideEvent(QHideEvent *) |
228 | { |
229 | mInfos.clear(); |
230 | mFunctioFullName = "" ; |
231 | } |
232 | |