• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

IJHack / QtPass / 25827655541

13 May 2026 09:32PM UTC coverage: 29.068% (-0.02%) from 29.083%
25827655541

push

github

web-flow
cleanup: drop AS_CONST macro + qApp deprecation pragmas (#1472)

Two small mechanical refactors that simplify the source without
changing behaviour.

(a) AS_CONST macro removal
--------------------------

src/helpers.h defined a single macro:

    #if __cplusplus >= 201703L
    #  define AS_CONST(x) std::as_const(x)
    #else
    #  define AS_CONST(x) qAsConst(x)
    #endif

The whole repo now requires C++17 (src/src.pro and tests/tests.pri both
say c++17; CLAUDE.md states "this repository enforces C++17 for all
builds"), so the macro is just an alias for std::as_const. It was used
in two places — switch them to std::as_const directly and delete
helpers.h. Also drop the now-unused #include "helpers.h" from
passworddialog.cpp (it had never used the macro).

(b) qApp deprecation pragmas
----------------------------

Two call sites used the qApp macro inside `#pragma GCC diagnostic
ignored "-Wdeprecated-declarations"` blocks (qApp is deprecated in Qt
6.0+). Replace qApp with QApplication::instance() so the deprecation
warning has nothing to fire on, and remove the surrounding pragma
push/pop blocks (~12 lines) — including the MSVC `#pragma warning`
variants.

No functional change. Tests:
- tst_util: 124/124
- tst_storemodel: 33/33
- tst_filecontent: 21/21
- doxygen: zero warnings from our code

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

1 of 5 new or added lines in 4 files covered. (20.0%)

3 existing lines in 2 files now uncovered.

1956 of 6729 relevant lines covered (29.07%)

26.91 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

6.72
/src/qtpass.cpp
1
// SPDX-FileCopyrightText: 2018 Anne Jan Brouwer
2
// SPDX-License-Identifier: GPL-3.0-or-later
3
#include "qtpass.h"
4
#include "mainwindow.h"
5
#include "qtpasssettings.h"
6
#include "util.h"
7
#include <QApplication>
8
#include <QClipboard>
9
#include <QDialog>
10
#include <QLabel>
11
#include <QPixmap>
12
#include <QVBoxLayout>
13

14
#ifndef Q_OS_WIN
15
#include <QInputDialog>
16
#include <QLineEdit>
17
#include <QMimeData>
18
#include <utility>
19
#else
20
#define WIN32_LEAN_AND_MEAN /*_KILLING_MACHINE*/
21
#define WIN32_EXTRA_LEAN
22
#include <windows.h>
23
#include <winnetwk.h>
24
#undef DELETE
25
#include <QMimeData>
26
#endif
27

28
#ifdef QT_DEBUG
29
#include "debughelper.h"
30
#endif
31

32
/**
33
 * @brief Constructs a QtPass instance.
34
 * @param mainWindow The main window reference
35
 */
36
QtPass::QtPass(MainWindow *mainWindow) : m_mainWindow(mainWindow) {
×
37
  setClipboardTimer();
×
38
  clearClipboardTimer.setSingleShot(true);
×
39
  connect(&clearClipboardTimer, &QTimer::timeout, this,
×
40
          &QtPass::clearClipboard);
×
41

NEW
42
  QObject::connect(QApplication::instance(), &QApplication::aboutToQuit, this,
×
UNCOV
43
                   &QtPass::clearClipboard);
×
44

UNCOV
45
  setMainWindow();
×
46
}
×
47

48
/**
49
 * @brief QtPass::~QtPass destroy!
50
 */
51
QtPass::~QtPass() {
×
52
#ifdef Q_OS_WIN
53
  if (QtPassSettings::isUseWebDav())
54
    WNetCancelConnection2A(QtPassSettings::getPassStore().toUtf8().constData(),
55
                           0, 1);
56
#else
57
  if (fusedav.state() == QProcess::Running) {
×
58
    fusedav.terminate();
×
59
    fusedav.waitForFinished(2000);
×
60
  }
61
#endif
62
}
×
63

64
/**
65
 * @brief QtPass::init make sure we are ready to go as soon as
66
 * possible
67
 */
68
auto QtPass::init() -> bool {
×
69
  QString passStore = QtPassSettings::getPassStore(Util::findPasswordStore());
×
70
  QtPassSettings::setPassStore(passStore);
×
71

72
  QtPassSettings::initExecutables();
×
73

74
  QString version = QtPassSettings::getVersion();
×
75

76
  // Config updates
77
  if (version.isEmpty()) {
×
78
#ifdef QT_DEBUG
79
    dbg() << "assuming fresh install";
80
#endif
81

82
    if (QtPassSettings::getAutoclearSeconds() < 5) {
×
83
      QtPassSettings::setAutoclearSeconds(10);
×
84
    }
85
    if (QtPassSettings::getAutoclearPanelSeconds() < 5) {
×
86
      QtPassSettings::setAutoclearPanelSeconds(10);
×
87
    }
88
    if (!QtPassSettings::getPwgenExecutable().isEmpty()) {
×
89
      QtPassSettings::setUsePwgen(true);
×
90
    } else {
91
      QtPassSettings::setUsePwgen(false);
×
92
    }
93
    QtPassSettings::setPassTemplate("login\nurl");
×
94
  } else {
95
    if (QtPassSettings::getPassTemplate().isEmpty()) {
×
96
      QtPassSettings::setPassTemplate("login\nurl");
×
97
    }
98
  }
99

100
  QtPassSettings::setVersion(VERSION);
×
101

102
  if (!Util::configIsValid()) {
×
103
    m_mainWindow->config();
×
104
    if (freshStart && !Util::configIsValid()) {
×
105
      return false;
106
    }
107
  }
108

109
  // Note: WebDAV mount needs to happen before accessing the store,
110
  // but ideally should be done after Window is shown to avoid long delay.
111
  if (QtPassSettings::isUseWebDav()) {
×
112
    mountWebDav();
×
113
  }
114

115
  freshStart = false;
×
116
  return true;
×
117
}
118

119
/**
120
 * @brief Sets up the main window and connects signal handlers.
121
 */
122
void QtPass::setMainWindow() {
×
123
  m_mainWindow->restoreWindow();
×
124

125
  fusedav.setParent(m_mainWindow);
×
126

127
  // Signal handlers are connected for both pass implementations
128
  // Note: When pass binary changes, QtPass restart is required to reconnect
129
  // This is acceptable as pass binary change is infrequent
130
  connectPassSignalHandlers(QtPassSettings::getRealPass());
×
131
  connectPassSignalHandlers(QtPassSettings::getImitatePass());
×
132

133
  connect(m_mainWindow, &MainWindow::passShowHandlerFinished, this,
×
134
          &QtPass::passShowHandlerFinished);
×
135

136
  // only for ipass
137
  connect(QtPassSettings::getImitatePass(), &ImitatePass::startReencryptPath,
×
138
          m_mainWindow, &MainWindow::startReencryptPath);
×
139
  connect(QtPassSettings::getImitatePass(), &ImitatePass::endReencryptPath,
×
140
          m_mainWindow, &MainWindow::endReencryptPath);
×
141

142
  connect(m_mainWindow, &MainWindow::passGitInitNeeded, []() {
×
143
#ifdef QT_DEBUG
144
    dbg() << "Pass git init called";
145
#endif
146
    QtPassSettings::getPass()->GitInit();
×
147
  });
×
148

149
  connect(m_mainWindow, &MainWindow::generateGPGKeyPair, m_mainWindow,
×
150
          [this](const QString &batch) {
×
151
            QtPassSettings::getPass()->GenerateGPGKeys(batch);
×
152
            m_mainWindow->showStatusMessage(tr("Generating GPG key pair"),
×
153
                                            60000);
154
          });
×
155
}
×
156

157
/**
158
 * @brief Connects pass signal handlers to QtPass slots.
159
 * @param pass The pass instance to connect
160
 */
161
void QtPass::connectPassSignalHandlers(Pass *pass) {
×
162
  connect(pass, &Pass::error, this, &QtPass::processError);
×
163
  connect(pass, &Pass::processErrorExit, this, &QtPass::processErrorExit);
×
164
  connect(pass, &Pass::critical, m_mainWindow, &MainWindow::critical);
×
165
  connect(pass, &Pass::startingExecuteWrapper, m_mainWindow,
×
166
          &MainWindow::executeWrapperStarted);
×
167
  connect(pass, &Pass::statusMsg, m_mainWindow, &MainWindow::showStatusMessage);
×
168
  connect(pass, &Pass::finishedShow, m_mainWindow,
×
169
          &MainWindow::passShowHandler);
×
170
  connect(pass, &Pass::finishedOtpGenerate, m_mainWindow,
×
171
          &MainWindow::passOtpHandler);
×
172

173
  connect(pass, &Pass::finishedGitInit, this, &QtPass::passStoreChanged);
×
174
  connect(pass, &Pass::finishedGitPull, this, &QtPass::processFinished);
×
175
  connect(pass, &Pass::finishedGitPush, this, &QtPass::processFinished);
×
176
  connect(pass, &Pass::finishedInsert, this, &QtPass::finishedInsert);
×
177
  connect(pass, &Pass::finishedRemove, this, &QtPass::passStoreChanged);
×
178
  connect(pass, &Pass::finishedInit, this, &QtPass::passStoreChanged);
×
179
  connect(pass, &Pass::finishedMove, this, &QtPass::passStoreChanged);
×
180
  connect(pass, &Pass::finishedCopy, this, &QtPass::passStoreChanged);
×
181
  connect(pass, &Pass::finishedGenerateGPGKeys, this,
×
182
          &QtPass::onKeyGenerationComplete);
×
183
  connect(pass, &Pass::finishedGrep, m_mainWindow, &MainWindow::onGrepFinished);
×
184
}
×
185

186
/**
187
 * @brief QtPass::mountWebDav is some scary voodoo magic
188
 */
189
void QtPass::mountWebDav() {
×
190
#ifdef Q_OS_WIN
191
  char dst[20] = {0};
192
  NETRESOURCEA netres;
193
  memset(&netres, 0, sizeof(netres));
194
  netres.dwType = RESOURCETYPE_DISK;
195
  netres.lpLocalName = nullptr;
196
  // Store QByteArray in variables to ensure lifetime during WNetUseConnectionA
197
  // call
198
  QByteArray webDavUrlUtf8 = QtPassSettings::getWebDavUrl().toUtf8();
199
  QByteArray webDavPasswordUtf8 = QtPassSettings::getWebDavPassword().toUtf8();
200
  QByteArray webDavUserUtf8 = QtPassSettings::getWebDavUser().toUtf8();
201
  netres.lpRemoteName = const_cast<char *>(webDavUrlUtf8.constData());
202
  DWORD size = sizeof(dst);
203
  DWORD r = WNetUseConnectionA(
204
      reinterpret_cast<HWND>(m_mainWindow->effectiveWinId()), &netres,
205
      const_cast<char *>(webDavPasswordUtf8.constData()),
206
      const_cast<char *>(webDavUserUtf8.constData()),
207
      CONNECT_TEMPORARY | CONNECT_INTERACTIVE | CONNECT_REDIRECT, dst, &size,
208
      0);
209
  if (r == NO_ERROR) {
210
    QtPassSettings::setPassStore(dst);
211
  } else {
212
    char message[256] = {0};
213
    FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, 0, r, 0, message,
214
                   sizeof(message), 0);
215
    m_mainWindow->flashText(tr("Failed to connect WebDAV:\n") + message +
216
                                " (0x" + QString::number(r, 16) + ")",
217
                            true);
218
  }
219
#else
220
  fusedav.start("fusedav", QStringList()
×
221
                               << "-o"
×
222
                               << "nonempty"
×
223
                               << "-u"
×
224
                               << "\"" + QtPassSettings::getWebDavUser() + "\""
×
225
                               << QtPassSettings::getWebDavUrl()
×
226
                               << "\"" + QtPassSettings::getPassStore() + "\"");
×
227
  fusedav.waitForStarted();
×
228
  if (fusedav.state() == QProcess::Running) {
×
229
    QString pwd = QtPassSettings::getWebDavPassword();
×
230
    bool ok = true;
×
231
    if (pwd.isEmpty()) {
×
232
      pwd = QInputDialog::getText(m_mainWindow, tr("QtPass WebDAV password"),
×
233
                                  tr("Enter password to connect to WebDAV:"),
×
234
                                  QLineEdit::Password, "", &ok);
235
    }
236
    if (ok && !pwd.isEmpty()) {
×
237
      fusedav.write(pwd.toUtf8() + '\n');
×
238
      fusedav.closeWriteChannel();
×
239
      fusedav.waitForFinished(2000);
×
240
    } else {
241
      fusedav.terminate();
×
242
    }
243
  }
244
  QString error = fusedav.readAllStandardError();
×
245
  qsizetype prompt = error.indexOf("Password:");
×
246
  if (prompt >= 0) {
×
247
    error.remove(0, prompt + 10);
×
248
  }
249
  if (fusedav.state() != QProcess::Running) {
×
250
    error = tr("fusedav exited unexpectedly\n") + error;
×
251
  }
252
  if (error.size() > 0) {
×
253
    m_mainWindow->flashText(
×
254
        tr("Failed to start fusedav to connect WebDAV:\n") + error, true);
×
255
  }
256
#endif
257
}
×
258

259
/**
260
 * @brief QtPass::processError something went wrong
261
 * @param error
262
 */
263
void QtPass::processError(QProcess::ProcessError error) {
×
264
  QString errorString;
×
265
  switch (error) {
×
266
  case QProcess::FailedToStart:
×
267
    errorString = tr("QProcess::FailedToStart");
×
268
    break;
×
269
  case QProcess::Crashed:
×
270
    errorString = tr("QProcess::Crashed");
×
271
    break;
×
272
  case QProcess::Timedout:
×
273
    errorString = tr("QProcess::Timedout");
×
274
    break;
×
275
  case QProcess::ReadError:
×
276
    errorString = tr("QProcess::ReadError");
×
277
    break;
×
278
  case QProcess::WriteError:
×
279
    errorString = tr("QProcess::WriteError");
×
280
    break;
×
281
  case QProcess::UnknownError:
×
282
    errorString = tr("QProcess::UnknownError");
×
283
    break;
×
284
  }
285
  m_mainWindow->flashText(errorString, true);
×
286
  m_mainWindow->setUiElementsEnabled(true);
×
287
}
×
288

289
/**
290
 * @brief Handles process error exit.
291
 * @param exitCode The exit code
292
 * @param p_error The error message
293
 */
294
void QtPass::processErrorExit(int exitCode, const QString &p_error) {
×
295
  if (nullptr != m_mainWindow->getKeygenDialog()) {
×
296
    m_mainWindow->cleanKeygenDialog();
×
297
    if (exitCode != 0) {
×
298
      m_mainWindow->showStatusMessage(tr("GPG key pair generation failed"),
×
299
                                      10000);
300
    }
301
  }
302

303
  if (!p_error.isEmpty()) {
×
304
    QString output;
×
305
    QString error = p_error.toHtmlEscaped();
×
306
    if (exitCode == 0) {
×
307
      //  https://github.com/IJHack/qtpass/issues/111
308
      output = "<span style=\"color: darkgray;\">" + error + "</span><br />";
×
309
    } else {
310
      output = "<span style=\"color: red;\">" + error + "</span><br />";
×
311
    }
312

313
    output.replace(Util::protocolRegex(), R"(<a href="\1">\1</a>)");
×
314
    output.replace(QStringLiteral("\n"), "<br />");
×
315

316
    m_mainWindow->flashText(output, false, true);
×
317
  }
318

319
  m_mainWindow->setUiElementsEnabled(true);
×
320
}
×
321

322
/**
323
 * @brief QtPass::processFinished background process has finished
324
 * @param exitCode
325
 * @param exitStatus
326
 * @param output    stdout from a process
327
 * @param errout    stderr from a process
328
 */
329
void QtPass::processFinished(const QString &p_output, const QString &p_errout) {
×
330
  showInTextBrowser(p_output);
×
331
  //    Sometimes there is error output even with 0 exit code, which is
332
  //    assumed in this function
333
  processErrorExit(0, p_errout);
×
334

335
  m_mainWindow->setUiElementsEnabled(true);
×
336
}
×
337

338
/**
339
 * @brief Called when pass store has changed.
340
 * @param p_out Output from the process
341
 * @param p_err Error output
342
 */
343
void QtPass::passStoreChanged(const QString &p_out, const QString &p_err) {
×
344
  processFinished(p_out, p_err);
×
345
  doGitPush();
×
346
}
×
347

348
/**
349
 * @brief Called when an insert operation has finished.
350
 * @param p_output Output from the process
351
 * @param p_errout Error output
352
 */
353
void QtPass::finishedInsert(const QString &p_output, const QString &p_errout) {
×
354
  processFinished(p_output, p_errout);
×
355
  doGitPush();
×
356
  m_mainWindow->on_treeView_clicked(m_mainWindow->getCurrentTreeViewIndex());
×
357
}
×
358

359
/**
360
 * @brief Called when GPG key generation is complete.
361
 * @param p_output Standard output from the key generation process
362
 * @param p_errout Standard error output from the key generation process
363
 */
364
void QtPass::onKeyGenerationComplete(const QString &p_output,
×
365
                                     const QString &p_errout) {
366
  if (nullptr != m_mainWindow->getKeygenDialog()) {
×
367
#ifdef QT_DEBUG
368
    qDebug() << "Keygen Done";
369
#endif
370

371
    m_mainWindow->cleanKeygenDialog();
×
372
    m_mainWindow->showStatusMessage(tr("GPG key pair generated successfully"),
×
373
                                    10000);
374
  }
375

376
  processFinished(p_output, p_errout);
×
377
}
×
378

379
/**
380
 * @brief Called when the password show handler has finished.
381
 * @param output The password content to display
382
 */
383
void QtPass::passShowHandlerFinished(QString output) {
×
384
  showInTextBrowser(std::move(output));
×
385
}
×
386

387
/**
388
 * @brief Displays output text in the main window's text browser.
389
 * @param output The text to display
390
 * @param prefix Optional prefix to prepend to the output
391
 * @param postfix Optional postfix to append to the output
392
 */
393
void QtPass::showInTextBrowser(QString output, const QString &prefix,
×
394
                               const QString &postfix) {
395
  output = output.toHtmlEscaped();
×
396

397
  output.replace(Util::protocolRegex(), R"(<a href="\1">\1</a>)");
×
398
  output.replace(QStringLiteral("\n"), "<br />");
×
399
  output = prefix + output + postfix;
×
400

401
  m_mainWindow->flashText(output, false, true);
×
402
}
×
403

404
/**
405
 * @brief Performs automatic git push if enabled in settings.
406
 */
407
void QtPass::doGitPush() {
×
408
  if (QtPassSettings::isAutoPush()) {
×
409
    m_mainWindow->onPush();
×
410
  }
411
}
×
412

413
/**
414
 * @brief Sets the text to be stored in clipboard and handles clipboard
415
 * operations.
416
 * @param password The password or text to store
417
 * @param p_output Additional output text
418
 */
419
void QtPass::setClippedText(const QString &password, const QString &p_output) {
×
420
  if (QtPassSettings::getClipBoardType() != Enums::CLIPBOARD_NEVER &&
×
421
      !p_output.isEmpty()) {
422
    clippedText = password;
×
423
    if (QtPassSettings::getClipBoardType() == Enums::CLIPBOARD_ALWAYS) {
×
424
      copyTextToClipboard(password);
×
425
    }
426
  }
427
}
×
428
/**
429
 * @brief Clears the stored clipped text.
430
 */
431
void QtPass::clearClippedText() { clippedText = ""; }
×
432

433
/**
434
 * @brief Sets the clipboard clear timer based on autoclear settings.
435
 */
436
void QtPass::setClipboardTimer() {
×
437
  clearClipboardTimer.setInterval(MS_PER_SECOND *
×
438
                                  QtPassSettings::getAutoclearSeconds());
×
439
}
×
440

441
/**
442
 * @brief MainWindow::clearClipboard remove clipboard contents.
443
 */
444
void QtPass::clearClipboard() {
×
445
  QClipboard *clipboard = QApplication::clipboard();
×
446
  bool cleared = false;
447
  if (this->clippedText == clipboard->text(QClipboard::Selection)) {
×
448
    clipboard->clear(QClipboard::Selection);
×
449
    clipboard->setText(QString(""), QClipboard::Selection);
×
450
    cleared = true;
451
  }
452
  if (this->clippedText == clipboard->text(QClipboard::Clipboard)) {
×
453
    clipboard->clear(QClipboard::Clipboard);
×
454
    cleared = true;
455
  }
456
  if (cleared) {
×
457
    m_mainWindow->showStatusMessage(tr("Clipboard cleared"));
×
458
  } else {
459
    m_mainWindow->showStatusMessage(tr("Clipboard not cleared"));
×
460
  }
461

462
  clippedText.clear();
×
463
}
×
464

465
/**
466
 * @brief Build clipboard MIME data with platform-specific security hints.
467
 * @param text - Plain text to copy
468
 * @return QMimeData with text and security hints
469
 */
470
auto buildClipboardMimeData(const QString &text) -> QMimeData * {
1✔
471
  auto *mimeData = new QMimeData();
1✔
472
  mimeData->setText(text);
1✔
473
#ifdef Q_OS_LINUX
474
  mimeData->setData("x-kde-passwordManagerHint", QByteArray("secret"));
2✔
475
#endif
476
#ifdef Q_OS_MAC
477
  mimeData->setData("application/x-nspasteboard-concealed-type", QByteArray());
478
#endif
479
#ifdef Q_OS_WIN
480
  mimeData->setData("ExcludeClipboardContentFromMonitorProcessing",
481
                    dwordBytes(1));
482
  mimeData->setData("CanIncludeInClipboardHistory", dwordBytes(0));
483
  mimeData->setData("CanUploadToCloudClipboard", dwordBytes(0));
484
#endif
485
  return mimeData;
1✔
486
}
487

488
/**
489
 * @brief MainWindow::copyTextToClipboard copies text to your clipboard
490
 * @param text
491
 */
492
void QtPass::copyTextToClipboard(const QString &text) {
×
493
  QClipboard *clip = QApplication::clipboard();
×
494

495
  QClipboard::Mode mode = QClipboard::Clipboard;
496
  if (QtPassSettings::isUseSelection() && clip->supportsSelection()) {
×
497
    mode = QClipboard::Selection;
498
  }
499

500
  auto *mimeData = buildClipboardMimeData(text);
×
501
  clip->setMimeData(mimeData, mode);
×
502

503
  clippedText = text;
×
504
  m_mainWindow->showStatusMessage(tr("Copied to clipboard"));
×
505
  if (QtPassSettings::isUseAutoclear()) {
×
506
    clearClipboardTimer.start();
×
507
  }
508
}
×
509

510
/**
511
 * @brief displays the text as qrcode
512
 * @param text
513
 */
514
void QtPass::showTextAsQRCode(const QString &text) {
×
515
  QProcess qrencode;
×
516
  qrencode.start(QtPassSettings::getQrencodeExecutable("/usr/bin/qrencode"),
×
517
                 QStringList() << "-o-"
×
518
                               << "-tPNG");
×
519
  qrencode.write(text.toUtf8());
×
520
  qrencode.closeWriteChannel();
×
521
  qrencode.waitForFinished();
×
522
  QByteArray output(qrencode.readAllStandardOutput());
×
523

524
  if (qrencode.exitStatus() || qrencode.exitCode()) {
×
525
    QString error(qrencode.readAllStandardError());
×
526
    m_mainWindow->showStatusMessage(error);
×
527
  } else {
528
    QPixmap image;
×
529
    image.loadFromData(output, "PNG");
×
530
    QDialog *popup = createQRCodePopup(image);
×
531
    popup->exec();
×
532
  }
×
533
}
×
534

535
/**
536
 * @brief QtPass::createQRCodePopup creates a popup dialog with the given QR
537
 * code image. This is extracted for testability. The caller is responsible
538
 * for showing and managing the popup lifecycle.
539
 * @param image The QR code pixmap to display
540
 * @return The created popup dialog
541
 */
542
QDialog *QtPass::createQRCodePopup(const QPixmap &image) {
1✔
543
  auto *popup = new QDialog(nullptr, Qt::Popup | Qt::FramelessWindowHint);
1✔
544
  popup->setAttribute(Qt::WA_DeleteOnClose);
1✔
545
  auto *layout = new QVBoxLayout;
1✔
546
  auto *popupLabel = new QLabel();
1✔
547
  layout->addWidget(popupLabel);
1✔
548
  popupLabel->setPixmap(image);
1✔
549
  popupLabel->setScaledContents(true);
1✔
550
  popupLabel->show();
1✔
551
  popup->setLayout(layout);
1✔
552
  popup->move(QCursor::pos());
1✔
553
  return popup;
1✔
554
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc