aboutsummaryrefslogtreecommitdiffstats
path: root/ui/qt/utils/qt_ui_utils.cpp
blob: eb6308bf0cde2e0b8dfe5daac8249e4a22d7bd64 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
/* qt_ui_utils.cpp
 *
 * Wireshark - Network traffic analyzer
 * By Gerald Combs <gerald@wireshark.org>
 * Copyright 1998 Gerald Combs
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <ui/qt/utils/qt_ui_utils.h>

#include <epan/addr_resolv.h>
#include <epan/range.h>
#include <epan/to_str.h>
#include <epan/value_string.h>
#include <epan/prefs.h>

#include <ui/recent.h>
#include <ui/last_open_dir.h>
#include "ui/ws_ui_util.h"

#include <wsutil/str_util.h>

#include <ui/qt/main_application.h>

#include <QAction>
#include <QApplication>
#include <QDateTime>
#include <QDesktopServices>
#include <QDir>
#include <QFileInfo>
#include <QFontDatabase>
#include <QProcess>
#include <QUrl>
#include <QUuid>
#include <QScreen>

/*
 * We might want to create our own "wsstring" class with convenience
 * methods for handling g_malloc()ed strings, GStrings, and a shortcut
 * to .toUtf8().constData().
 */

gchar *qstring_strdup(QString q_string) {
    return g_strdup(q_string.toUtf8().constData());
}

QString gchar_free_to_qstring(gchar *glib_string) {
    return QString(gchar_free_to_qbytearray(glib_string));
}

QByteArray gchar_free_to_qbytearray(gchar *glib_string)
{
    QByteArray qt_bytearray(glib_string);
    g_free(glib_string);
    return qt_bytearray;
}

QByteArray gstring_free_to_qbytearray(GString *glib_gstring)
{
    QByteArray qt_ba(glib_gstring->str);
    g_string_free(glib_gstring, TRUE);
    return qt_ba;
}

QByteArray gbytearray_free_to_qbytearray(GByteArray *glib_array)
{
    QByteArray qt_ba(reinterpret_cast<char *>(glib_array->data), glib_array->len);
    g_byte_array_free(glib_array, TRUE);
    return qt_ba;
}

const QString int_to_qstring(qint64 value, int field_width, int base)
{
    // Qt deprecated QString::sprintf in Qt 5.0, then added ::asprintf in
    // Qt 5.5. Rather than navigate a maze of QT_VERSION_CHECKs, just use
    // QString::arg.
    QString int_qstr;

    switch (base) {
    case 8:
        int_qstr = "0";
        break;
    case 16:
        int_qstr = "0x";
        break;
    default:
        break;
    }

    int_qstr += QString("%1").arg(value, field_width, base, QChar('0'));
    return int_qstr;
}

const QString address_to_qstring(const _address *address, bool enclose)
{
    QString address_qstr = QString();
    if (address) {
        if (enclose && address->type == AT_IPv6) address_qstr += "[";
        gchar *address_gchar_p = address_to_str(NULL, address);
        address_qstr += address_gchar_p;
        wmem_free(NULL, address_gchar_p);
        if (enclose && address->type == AT_IPv6) address_qstr += "]";
    }
    return address_qstr;
}

const QString address_to_display_qstring(const _address *address)
{
    QString address_qstr = QString();
    if (address) {
        gchar *address_gchar_p = address_to_display(NULL, address);
        address_qstr = address_gchar_p;
        wmem_free(NULL, address_gchar_p);
    }
    return address_qstr;
}

const QString val_to_qstring(const guint32 val, const value_string *vs, const char *fmt)
{
    QString val_qstr;
    gchar* gchar_p = val_to_str_wmem(NULL, val, vs, fmt);
    val_qstr = gchar_p;
    wmem_free(NULL, gchar_p);

    return val_qstr;
}

const QString val_ext_to_qstring(const guint32 val, value_string_ext *vse, const char *fmt)
{
    QString val_qstr;
    gchar* gchar_p = val_to_str_ext_wmem(NULL, val, vse, fmt);
    val_qstr = gchar_p;
    wmem_free(NULL, gchar_p);

    return val_qstr;
}

const QString range_to_qstring(const range_string *range)
{
    QString range_qstr = QString();
    if (range) {
        range_qstr += QString("%1-%2").arg(range->value_min).arg(range->value_max);
    }
    return range_qstr;
}

const QString bits_s_to_qstring(const double bits_s)
{
    return gchar_free_to_qstring(
                format_size(bits_s, FORMAT_SIZE_UNIT_NONE, FORMAT_SIZE_PREFIX_SI));
}

const QString file_size_to_qstring(const gint64 size)
{
    return gchar_free_to_qstring(
                format_size(size, FORMAT_SIZE_UNIT_BYTES, FORMAT_SIZE_PREFIX_SI));
}

const QString time_t_to_qstring(time_t ti_time)
{
    QDateTime date_time = QDateTime::fromSecsSinceEpoch(qint64(ti_time));
    QString time_str = date_time.toLocalTime().toString("yyyy-MM-dd hh:mm:ss");
    return time_str;
}

QString html_escape(const QString plain_string) {
    return plain_string.toHtmlEscaped();
}


void smooth_font_size(QFont &font) {
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
    QList<int> size_list = QFontDatabase::smoothSizes(font.family(), font.styleName());
#else
    QFontDatabase fdb;
    QList<int> size_list = fdb.smoothSizes(font.family(), font.styleName());
#endif

    if (size_list.size() < 2) return;

    int last_size = size_list.takeFirst();
    foreach (int cur_size, size_list) {
        if (font.pointSize() > last_size && font.pointSize() <= cur_size) {
            font.setPointSize(cur_size);
            return;
        }
        last_size = cur_size;
    }
}

bool qActionLessThan(const QAction * a1, const QAction * a2) {
    return a1->text().compare(a2->text()) < 0;
}

bool qStringCaseLessThan(const QString &s1, const QString &s2)
{
    return s1.compare(s2, Qt::CaseInsensitive) < 0;
}

void desktop_show_in_folder(const QString file_path)
{
    bool success = false;

    // https://stackoverflow.com/questions/3490336/how-to-reveal-in-finder-or-show-in-explorer-with-qt

#if defined(Q_OS_WIN)
    QString command = "explorer.exe";
    QStringList arguments;
    QString path = QDir::toNativeSeparators(file_path);
    arguments << "/select," << path + "";
    success = QProcess::startDetached(command, arguments);
#elif defined(Q_OS_MAC)
    QStringList script_args;
    QString escaped_path = file_path;

    escaped_path.replace('"', "\\\"");
    script_args << "-e"
               << QString("tell application \"Finder\" to reveal POSIX file \"%1\"")
                                     .arg(escaped_path);
    if (QProcess::execute("/usr/bin/osascript", script_args) == 0) {
        success = true;
        script_args.clear();
        script_args << "-e"
                   << "tell application \"Finder\" to activate";
        QProcess::execute("/usr/bin/osascript", script_args);
    }
#else
    // Is there a way to highlight the file using xdg-open?
#endif
    if (!success) {
        QFileInfo file_info(file_path);
        QDesktopServices::openUrl(QUrl::fromLocalFile(file_info.dir().absolutePath()));
    }
}

bool rect_on_screen(const QRect &rect)
{
    foreach (QScreen *screen, qApp->screens()) {
        if (screen->availableGeometry().contains(rect)) {
            return true;
        }
    }

    return false;
}

void set_action_shortcuts_visible_in_context_menu(QList<QAction *> actions)
{
#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) && QT_VERSION < QT_VERSION_CHECK(5, 13, 0)
    // For QT_VERSION >= 5.13.0 we call styleHints()->setShowShortcutsInContextMenus(true)
    // in WiresharkApplication.
    // QTBUG-71471
    // QTBUG-61181
    foreach (QAction *action, actions) {
        action->setShortcutVisibleInContextMenu(true);
    }
#else
    Q_UNUSED(actions)
#endif
}

QVector<rtpstream_id_t *>qvector_rtpstream_ids_copy(QVector<rtpstream_id_t *> stream_ids)
{
    QVector<rtpstream_id_t *>new_ids;

    foreach(rtpstream_id_t *id, stream_ids) {
        rtpstream_id_t *new_id = g_new0(rtpstream_id_t, 1);
        rtpstream_id_copy(id, new_id);
        new_ids << new_id;
    }

    return new_ids;
}

void qvector_rtpstream_ids_free(QVector<rtpstream_id_t *> stream_ids)
{
    foreach(rtpstream_id_t *id, stream_ids) {
        rtpstream_id_free(id);
    }
}

QString make_filter_based_on_rtpstream_id(QVector<rtpstream_id_t *> stream_ids)
{
    QStringList stream_filters;
    QString filter;

    foreach(rtpstream_id_t *id, stream_ids) {
        QString ip_proto = id->src_addr.type == AT_IPv6 ? "ipv6" : "ip";
        stream_filters << QString("(%1.src==%2 && udp.srcport==%3 && %1.dst==%4 && udp.dstport==%5 && rtp.ssrc==0x%6)")
                         .arg(ip_proto) // %1
                         .arg(address_to_qstring(&id->src_addr)) // %2
                         .arg(id->src_port) // %3
                         .arg(address_to_qstring(&id->dst_addr)) // %4
                         .arg(id->dst_port) // %5
                         .arg(id->ssrc, 0, 16);
    }
    if (stream_filters.length() > 0) {
        filter = stream_filters.join(" || ");
    }

    return filter;
}

QString lastOpenDir()
{
    QString result;

    switch (prefs.gui_fileopen_style) {

    case FO_STYLE_LAST_OPENED:
        /* The user has specified that we should start out in the last directory
           we looked in.  If we've already opened a file, use its containing
           directory, if we could determine it, as the directory, otherwise
           use the "last opened" directory saved in the preferences file if
           there was one. */
        /* This is now the default behaviour in file_selection_new() */
        result = QString(get_last_open_dir());
        break;

    case FO_STYLE_SPECIFIED:
        /* The user has specified that we should always start out in a
           specified directory; if they've specified that directory,
           start out by showing the files in that dir. */
        if (prefs.gui_fileopen_dir[0] != '\0')
            result = QString(prefs.gui_fileopen_dir);
        break;
    }

    QDir ld(result);
    if (ld.exists())
        return result;

    return QString();
}

void storeLastDir(QString dir)
{
    if (mainApp && dir.length() > 0)
        mainApp->setLastOpenDir(qUtf8Printable(dir));
}