From 73c01d6d0562f138b3aad83b6b2dcf8d3f09dcee Mon Sep 17 00:00:00 2001 From: Roland Knall Date: Wed, 22 Nov 2017 16:54:32 +0100 Subject: [PATCH] Qt: Rewrite the About dialog to use models Rewrite of the about dialog, to use QTableView and Models instead of HTML files. Everything is now model based, and the model is generic enough to support any variation which can be put into a QStringList row. Change-Id: Ie32bf66b2fe2a7754c0bf07205a7b068d46b0070 Reviewed-on: https://code.wireshark.org/review/24534 Petri-Dish: Roland Knall Tested-by: Petri Dish Buildbot Reviewed-by: Anders Broman --- ui/qt/CMakeLists.txt | 6 + ui/qt/Makefile.am | 6 + ui/qt/about_dialog.cpp | 476 +++++++++++++----------- ui/qt/about_dialog.h | 83 ++++- ui/qt/about_dialog.ui | 65 +++- ui/qt/models/astringlist_list_model.cpp | 169 +++++++++ ui/qt/models/astringlist_list_model.h | 92 +++++ ui/qt/models/html_text_delegate.cpp | 66 ++++ ui/qt/models/html_text_delegate.h | 48 +++ ui/qt/models/url_link_delegate.cpp | 68 ++++ ui/qt/models/url_link_delegate.h | 35 ++ 11 files changed, 858 insertions(+), 256 deletions(-) create mode 100644 ui/qt/models/astringlist_list_model.cpp create mode 100644 ui/qt/models/astringlist_list_model.h create mode 100644 ui/qt/models/html_text_delegate.cpp create mode 100644 ui/qt/models/html_text_delegate.h create mode 100644 ui/qt/models/url_link_delegate.cpp create mode 100644 ui/qt/models/url_link_delegate.h diff --git a/ui/qt/CMakeLists.txt b/ui/qt/CMakeLists.txt index b3bdbc4703..19496e154a 100644 --- a/ui/qt/CMakeLists.txt +++ b/ui/qt/CMakeLists.txt @@ -60,9 +60,11 @@ set(WIRESHARK_UTILS_HEADERS ) set(WIRESHARK_MODEL_HEADERS + models/astringlist_list_model.h models/cache_proxy_model.h models/decode_as_delegate.h models/decode_as_model.h + models/html_text_delegate.h models/interface_sort_filter_model.h models/interface_tree_cache_model.h models/interface_tree_model.h @@ -76,6 +78,7 @@ set(WIRESHARK_MODEL_HEADERS models/sparkline_delegate.h models/uat_delegate.h models/uat_model.h + models/url_link_delegate.h models/voip_calls_info_model.h ) @@ -263,9 +266,11 @@ set(WIRESHARK_UTILS_SRCS ) set(WIRESHARK_MODEL_SRCS + models/astringlist_list_model.cpp models/cache_proxy_model.cpp models/decode_as_delegate.cpp models/decode_as_model.cpp + models/html_text_delegate.cpp models/interface_sort_filter_model.cpp models/interface_tree_cache_model.cpp models/interface_tree_model.cpp @@ -280,6 +285,7 @@ set(WIRESHARK_MODEL_SRCS models/timeline_delegate.cpp models/uat_delegate.cpp models/uat_model.cpp + models/url_link_delegate.cpp models/voip_calls_info_model.cpp ) diff --git a/ui/qt/Makefile.am b/ui/qt/Makefile.am index 3d071657c1..beba9cc8ae 100644 --- a/ui/qt/Makefile.am +++ b/ui/qt/Makefile.am @@ -189,9 +189,11 @@ MOC_UTILS_HDRS = \ # Files for delegates and models MOC_MODELS_HDRS = \ + models/astringlist_list_model.h \ models/cache_proxy_model.h \ models/decode_as_delegate.h \ models/decode_as_model.h \ + models/html_text_delegate.h \ models/interface_sort_filter_model.h \ models/interface_tree_cache_model.h \ models/interface_tree_model.h \ @@ -205,6 +207,7 @@ MOC_MODELS_HDRS = \ models/sparkline_delegate.h \ models/uat_delegate.h \ models/uat_model.h \ + models/url_link_delegate.h \ models/voip_calls_info_model.h @@ -505,9 +508,11 @@ WIRESHARK_QT_UTILS_SRC = \ utils/qt_ui_utils.cpp WIRESHARK_QT_MODELS_SRCS = \ + models/astringlist_list_model.cpp \ models/cache_proxy_model.cpp \ models/decode_as_delegate.cpp \ models/decode_as_model.cpp \ + models/html_text_delegate.cpp \ models/interface_sort_filter_model.cpp \ models/interface_tree_cache_model.cpp \ models/interface_tree_model.cpp \ @@ -521,6 +526,7 @@ WIRESHARK_QT_MODELS_SRCS = \ models/timeline_delegate.cpp \ models/uat_model.cpp \ models/uat_delegate.cpp \ + models/url_link_delegate.cpp \ models/voip_calls_info_model.cpp WIRESHARK_QT_SRC = \ diff --git a/ui/qt/about_dialog.cpp b/ui/qt/about_dialog.cpp index 79b53eb0b6..4b73a990a1 100644 --- a/ui/qt/about_dialog.cpp +++ b/ui/qt/about_dialog.cpp @@ -4,19 +4,7 @@ * By Gerald Combs * Copyright 1998 Gerald Combs * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * SPDX-License-Identifier: GPL-2.0+ */ #include "config.h" @@ -58,33 +46,66 @@ #endif #include +#include +#include +#include #include #include #include #include +#include +#include +#include - -// To do: -// - Tweak and enhance ui... - -const QString AboutDialog::about_folders_row(const char *name, const QString dir, const char *typ_file) +AuthorListModel::AuthorListModel(QObject * parent) : +AStringListListModel(parent) { - int one_em = fontMetrics().height(); + bool readAck = false; + QFile f_authors; - QString short_dir = fontMetrics().elidedText(dir, Qt::ElideMiddle, one_em * 18); // Arbitrary + f_authors.setFileName(get_datafile_path("AUTHORS-SHORT")); + f_authors.open(QFile::ReadOnly | QFile::Text); + QTextStream ReadFile_authors(&f_authors); + ReadFile_authors.setCodec("UTF-8"); + + QRegExp rx("(.*)[<(]([\\s'a-zA-Z0-9._%+-]+(\\[[Aa][Tt]\\])?[a-zA-Z0-9._%+-]+)[>)]"); + acknowledgement_.clear(); + while (!ReadFile_authors.atEnd()) { + QString line = ReadFile_authors.readLine(); + + if ( ! readAck ) + { + if ( line.trimmed().length() == 0 ) + continue; + if ( line.startsWith("------") ) + continue; + } + + if ( line.compare(QStringLiteral("Acknowledgements") ) == 0 ) + readAck = true; + else if ( rx.indexIn(line) != -1 ) + appendRow( QStringList() << rx.cap(1).trimmed() << rx.cap(2).trimmed()); + + if ( readAck ) + acknowledgement_.append(QString("%1\n").arg(line)); + } + f_authors.close(); - // It would be really nice to be able to add a tooltip with the - // full path here but Qt's rich text doesn't appear to support - // "a title=". - return QString("%1%3%4\n") - .arg(name) - .arg(QUrl::fromLocalFile(dir).toString()) - .arg(short_dir) - .arg(typ_file); } -#if defined(HAVE_PLUGINS) || defined(HAVE_LUA) +AuthorListModel::~AuthorListModel() { } + +QString AuthorListModel::acknowledgment() const +{ + return acknowledgement_; +} + +QStringList AuthorListModel::headerColumns() const +{ + return QStringList() << tr("Name") << tr("E-Mail"); +} + static void plugins_add_description(const char *name, const char *version, const char *types, const char *filename, void *user_data) @@ -93,13 +114,10 @@ static void plugins_add_description(const char *name, const char *version, QStringList plugin_row = QStringList() << name << version << types << filename; *plugin_data << plugin_row; } -#endif -const QString AboutDialog::plugins_scan() +PluginListModel::PluginListModel(QObject * parent) : AStringListListModel(parent) { QList plugin_data; - QString plugin_table; - #ifdef HAVE_PLUGINS plugins_get_descriptions(plugins_add_description, &plugin_data); #endif @@ -108,18 +126,6 @@ const QString AboutDialog::plugins_scan() wslua_plugins_get_descriptions(plugins_add_description, &plugin_data); #endif - int one_em = fontMetrics().height(); - QString short_file; - - foreach (QStringList plugin_row, plugin_data) { - short_file = fontMetrics().elidedText(plugin_row[3], Qt::ElideMiddle, one_em * 22); // Arbitrary - plugin_table += QString("%1%2%3%4\n") - .arg(plugin_row[0]) // Name - .arg(plugin_row[1]) // Version - .arg(plugin_row[2]) // Type - .arg(short_file); - } - #ifdef HAVE_EXTCAP GHashTable * tools = extcap_loaded_interfaces(); if (tools && g_hash_table_size(tools) > 0) { @@ -127,40 +133,167 @@ const QString AboutDialog::plugins_scan() while (walker && walker->data) { extcap_info * tool = (extcap_info *)g_hash_table_lookup(tools, walker->data); if (tool) { - short_file = fontMetrics().elidedText(tool->full_path, Qt::ElideMiddle, one_em*22); - plugin_table += QString("%1%2%3%4\n") - .arg(tool->basename) // Name - .arg(tool->version) // Version - .arg("extcap") // Type - .arg(short_file); + QStringList plugin_row = QStringList() << tool->basename << tool->version << "extcap" << tool->full_path; + plugin_data << plugin_row; } walker = g_list_next(walker); } } #endif - return plugin_table; + typeNames_ << QString(""); + foreach(QStringList row, plugin_data) + { + typeNames_ << row.at(2); + appendRow(row); + } + + typeNames_.sort(); + typeNames_.removeDuplicates(); } +QStringList PluginListModel::typeNames() const +{ + return typeNames_; +} + +QStringList PluginListModel::headerColumns() const +{ + return QStringList() << tr("Name") << tr("Version") << tr("Type") << tr("Path"); +} + +ShortcutListModel::ShortcutListModel(QObject * parent): + AStringListListModel(parent) +{ + QMap > shortcuts; // name -> (shortcut, description) + foreach (const QWidget *child, wsApp->mainWindow()->findChildren()) { + // Recent items look funny here. + if (child->objectName().compare("menuOpenRecentCaptureFile") == 0) continue; + foreach (const QAction *action, child->actions()) { + + if (!action->shortcut().isEmpty()) { + QString name = action->text(); + name.replace('&', ""); + shortcuts[name] = QPair(action->shortcut().toString(QKeySequence::NativeText), action->toolTip()); + } + } + } + + QStringList names = shortcuts.keys(); + names.sort(); + foreach (const QString &name, names) { + QStringList row; + row << shortcuts[name].first << name << shortcuts[name].second; + appendRow(row); + } +} + +QStringList ShortcutListModel::headerColumns() const +{ + return QStringList() << tr("Shortcut") << tr("Name") << tr("Description"); +} + +FolderListModel::FolderListModel(QObject * parent): + AStringListListModel(parent) +{ + /* "file open" */ + appendRow( QStringList() << "\"File\" dialogs" << get_last_open_dir() << "capture files"); + + /* temp */ + appendRow( QStringList() << "Temp" << g_get_tmp_dir() << "untitled capture files"); + + /* pers conf */ + appendRow( QStringList() << "Personal configuration" + << gchar_free_to_qstring(get_persconffile_path("", FALSE)) + << "dfilters, preferences, ethers, " UTF8_HORIZONTAL_ELLIPSIS); + + /* global conf */ + QString dirPath = get_datafile_dir(); + if (! dirPath.isEmpty()) { + appendRow ( QStringList() << "Global configuration" << dirPath + << "dfilters, preferences, manuf, " UTF8_HORIZONTAL_ELLIPSIS); + } + + /* system */ + appendRow( QStringList() << "System" << get_systemfile_dir() << "ethers, ipxnets"); + + /* program */ + appendRow( QStringList() << "Program" << get_progfile_dir() << "program files"); + +#ifdef HAVE_PLUGINS + /* pers plugins */ + appendRow( QStringList() << "Personal Plugins" << get_plugins_pers_dir_with_version() << "binary plugins"); + + /* global plugins */ + appendRow( QStringList() << "Global Plugins" << get_plugins_dir_with_version() << "binary plugins"); +#endif + +#ifdef HAVE_LUA + /* pers plugins */ + appendRow( QStringList() << "Personal Lua Plugins" << get_plugins_pers_dir() << "lua scripts"); + + /* global plugins */ + appendRow( QStringList() << "Global Lua Plugins" << get_plugins_dir() << "lua scripts"); +#endif + +#ifdef HAVE_EXTCAP + /* Extcap */ + QStringList extPaths = QString(get_extcap_dir()).split(G_SEARCHPATH_SEPARATOR_S); + + foreach(QString path, extPaths) + appendRow( QStringList() << "Extcap path" << path.trimmed() << "Extcap Plugins search path"); + +#endif + +#ifdef HAVE_GEOIP + /* GeoIP */ + QStringList geoIpPaths = QString(geoip_db_get_paths()).split(G_SEARCHPATH_SEPARATOR_S); + foreach(QString path, geoIpPaths) + appendRow( QStringList() << "GeoIP path" << path.trimmed() << "GeoIP database search path"); +#endif + +#ifdef HAVE_LIBSMI + /* SMI MIBs/PIBs */ + QStringList smiPaths = QString(oid_get_default_mib_path()).split(G_SEARCHPATH_SEPARATOR_S); + foreach(QString path, smiPaths) + appendRow( QStringList() << "MIB/PIB path" << path.trimmed() << "SMI MIB/PIB search path"); +#endif +} + +QStringList FolderListModel::headerColumns() const +{ + return QStringList() << tr("Name") << tr("Location") << tr("Typical Files"); +} + +// To do: +// - Tweak and enhance ui... + AboutDialog::AboutDialog(QWidget *parent) : - QDialog(NULL), + QDialog(parent), ui(new Ui::AboutDialog) { ui->setupUi(this); setAttribute(Qt::WA_DeleteOnClose, true); QFile f_license; - const char *constpath; QString message; -#if defined(HAVE_LIBSMI) || defined(HAVE_GEOIP) || defined(HAVE_EXTCAP) -#if defined(HAVE_LIBSMI) || defined(HAVE_GEOIP) - char *path = NULL; -#endif - gint i; - gchar **resultArray; -#endif - GString *comp_info_str = get_compiled_version_info(get_wireshark_qt_compiled_info, + + GString *comp_info_str = get_compiled_version_info(get_wireshark_qt_compiled_info, get_gui_compiled_info); - GString *runtime_info_str = get_runtime_version_info(get_wireshark_runtime_info); + GString *runtime_info_str = get_runtime_version_info(get_wireshark_runtime_info); + + + AuthorListModel * authorModel = new AuthorListModel(this); + AStringListListSortFilterProxyModel * proxyAuthorModel = new AStringListListSortFilterProxyModel(this); + proxyAuthorModel->setSourceModel(authorModel); + proxyAuthorModel->setColumnToFilter(0); + proxyAuthorModel->setColumnToFilter(1); + ui->tblAuthors->setModel(proxyAuthorModel); + ui->pte_Authors->clear(); + ui->pte_Authors->appendPlainText(authorModel->acknowledgment()); + ui->pte_Authors->moveCursor(QTextCursor::Start); + + ui->tblAuthors->horizontalHeader()->setStretchLastSection(true); + connect(ui->searchAuthors, SIGNAL(textChanged(QString)), proxyAuthorModel, SLOT(setFilter(QString))); /* Wireshark tab */ @@ -177,8 +310,7 @@ AboutDialog::AboutDialog(QWidget *parent) : "Wireshark is Open Source Software released under the GNU General Public License.\n" "\n" "Check the man page and http://www.wireshark.org for more information.") - .arg(get_ws_vcs_version_info()).arg(get_copyright_info()).arg(comp_info_str->str) - .arg(runtime_info_str->str); + .arg(get_ws_vcs_version_info(), get_copyright_info(), comp_info_str->str, runtime_info_str->str); ui->label_wireshark->setTextInteractionFlags(Qt::TextSelectableByMouse); ui->label_wireshark->setText(message); @@ -188,154 +320,46 @@ AboutDialog::AboutDialog(QWidget *parent) : ui->label_logo->setPixmap(QPixmap(":/about/wssplash_dev.png")); #endif - /* Authors */ - ui->pte_Authors->setFont(wsApp->monospaceFont()); - this->addAuthors(NULL); - /* Folders */ - - int one_em = fontMetrics().height(); - - // Couldn't get CSS to work. - message = QString("\n").arg(one_em / 4); - message += "\n"; - - /* "file open" */ - message += about_folders_row("\"File\" dialogs", get_last_open_dir(), "capture files"); - - /* temp */ - message += about_folders_row("Temp", g_get_tmp_dir(), "untitled capture files"); - - /* pers conf */ - message += about_folders_row("Personal configuration", - gchar_free_to_qstring(get_persconffile_path("", FALSE)), - "dfilters, preferences, ethers, " UTF8_HORIZONTAL_ELLIPSIS); - - /* global conf */ - constpath = get_datafile_dir(); - if (constpath != NULL) { - message += about_folders_row("Global configuration", constpath, - "dfilters, preferences, manuf, " UTF8_HORIZONTAL_ELLIPSIS); - } - - /* system */ - message += about_folders_row("System", get_systemfile_dir(), "ethers, ipxnets"); - - /* program */ - message += about_folders_row("Program", get_progfile_dir(), "program files"); - -#ifdef HAVE_PLUGINS - /* pers plugins */ - message += about_folders_row("Personal Plugins", get_plugins_pers_dir_with_version(), "binary plugins"); - - /* global plugins */ - message += about_folders_row("Global Plugins", get_plugins_dir_with_version(), "binary plugins"); -#endif - -#ifdef HAVE_LUA - /* pers plugins */ - message += about_folders_row("Personal Lua Plugins", get_plugins_pers_dir(), "lua scripts"); - - /* global plugins */ - message += about_folders_row("Global Lua Plugins", get_plugins_dir(), "lua scripts"); -#endif - -#ifdef HAVE_EXTCAP - /* Extcap */ - constpath = get_extcap_dir(); - - resultArray = g_strsplit(constpath, G_SEARCHPATH_SEPARATOR_S, 10); - - for(i = 0; resultArray[i]; i++) { - message += about_folders_row("Extcap path", g_strstrip(resultArray[i]), - "Extcap Plugins search path"); - } - g_strfreev(resultArray); -#endif - -#ifdef HAVE_GEOIP - /* GeoIP */ - path = geoip_db_get_paths(); - - resultArray = g_strsplit(path, G_SEARCHPATH_SEPARATOR_S, 10); - - for(i = 0; resultArray[i]; i++) { - message += about_folders_row("GeoIP path", g_strstrip(resultArray[i]), - "GeoIP database search path"); - } - g_strfreev(resultArray); - g_free(path); -#endif - -#ifdef HAVE_LIBSMI - /* SMI MIBs/PIBs */ - path = oid_get_default_mib_path(); - - resultArray = g_strsplit(path, G_SEARCHPATH_SEPARATOR_S, 10); - - for(i = 0; resultArray[i]; i++) { - message += about_folders_row("MIB/PIB path", g_strstrip(resultArray[i]), - "SMI MIB/PIB search path"); - } - g_strfreev(resultArray); - g_free(path); -#endif - - message += "
NameLocationTypical Files
"; - ui->label_folders->setText(message); + FolderListModel * folderModel = new FolderListModel(this); + AStringListListSortFilterProxyModel * folderProxyModel = new AStringListListSortFilterProxyModel(this); + folderProxyModel->setSourceModel(folderModel); + folderProxyModel->setColumnToFilter(1); + folderProxyModel->setFilterType(AStringListListSortFilterProxyModel::FilterByStart); + ui->tblFolders->setModel(folderProxyModel); + ui->tblFolders->setItemDelegateForColumn(1, new UrlLinkDelegate(this)); + ui->tblFolders->setItemDelegateForColumn(2, new HTMLTextDelegate(this)); + connect(ui->searchFolders, SIGNAL(textChanged(QString)), folderProxyModel, SLOT(setFilter(QString))); /* Plugins */ #if defined(HAVE_PLUGINS) || defined(HAVE_LUA) || defined(HAVE_EXTCAP) - message = QString("\n").arg(one_em / 4); - message += "\n"; - message += plugins_scan(); + PluginListModel * pluginModel = new PluginListModel(this); + AStringListListSortFilterProxyModel * pluginFilterModel = new AStringListListSortFilterProxyModel(this); + pluginFilterModel->setSourceModel(pluginModel); + pluginFilterModel->setColumnToFilter(0); + AStringListListSortFilterProxyModel * pluginTypeModel = new AStringListListSortFilterProxyModel(this); + pluginTypeModel->setSourceModel(pluginFilterModel); + pluginTypeModel->setColumnToFilter(2); + ui->tblPlugins->setModel(pluginTypeModel); + ui->tblPlugins->setItemDelegateForColumn(3, new UrlLinkDelegate(this)); + ui->cmbType->addItems(pluginModel->typeNames()); + connect(ui->searchPlugins, SIGNAL(textChanged(QString)), pluginFilterModel, SLOT(setFilter(QString))); + connect(ui->cmbType, SIGNAL(currentIndexChanged(QString)), pluginTypeModel, SLOT(setFilter(QString))); - message += "
NameVersionTypePath
"; - ui->te_plugins->setHtml(message); #else - ui->te_plugins->setVisible(false); + ui->tabWidget->removeTab(ui->tabWidget->indexOf(ui->tab_plugins)); #endif /* Shortcuts */ - bool have_shortcuts = false; - - if (parent) { - message = "

Main Window Keyboard Shortcuts

\n"; - message += QString("\n").arg(one_em / 4); - message += "\n"; - - QMap > shortcuts; // name -> (shortcut, description) - foreach (const QWidget *child, parent->findChildren()) { - // Recent items look funny here. - if (child->objectName().compare("menuOpenRecentCaptureFile") == 0) continue; - foreach (const QAction *action, child->actions()) { - - if (!action->shortcut().isEmpty()) { - QString name = action->text(); - name.replace('&', ""); - shortcuts[name] = QPair(action->shortcut().toString(QKeySequence::NativeText), action->toolTip()); - } - } - } - - QStringList names = shortcuts.keys(); - names.sort(); - foreach (const QString &name, names) { - message += QString("\n") - .arg(shortcuts[name].first) - .arg(name) - .arg(shortcuts[name].second); - have_shortcuts = true; - } - - message += "
ShortcutNameDescription
%1%2%3
"; - ui->te_shortcuts->setHtml(message); - - } - - ui->te_shortcuts->setVisible(have_shortcuts); + ShortcutListModel * shortcutModel = new ShortcutListModel(this); + AStringListListSortFilterProxyModel * shortcutProxyModel = new AStringListListSortFilterProxyModel(this); + shortcutProxyModel->setSourceModel(shortcutModel); + shortcutProxyModel->setColumnToFilter(1); + shortcutProxyModel->setColumnToFilter(2); + ui->tblShortcuts->setModel(shortcutProxyModel); + connect(ui->searchShortcuts, SIGNAL(textChanged(QString)), shortcutProxyModel, SLOT(setFilter(QString))); /* License */ @@ -352,31 +376,6 @@ AboutDialog::AboutDialog(QWidget *parent) : ui->pte_License->insertPlainText(ReadFile_license.readAll()); ui->pte_License->moveCursor(QTextCursor::Start); - connect(ui->searchAuthors, SIGNAL(textChanged(const QString &)), this, SLOT(updateAuthors(const QString &))); -} - -void AboutDialog::addAuthors(const QString& filter) -{ - QFile f_authors; - - f_authors.setFileName(get_datafile_path("AUTHORS-SHORT")); - f_authors.open(QFile::ReadOnly | QFile::Text); - QTextStream ReadFile_authors(&f_authors); - ReadFile_authors.setCodec("UTF-8"); - - ui->pte_Authors->clear(); - ui->pte_Authors->moveCursor(QTextCursor::Start); - while (!ReadFile_authors.atEnd()) { - QString line = ReadFile_authors.readLine(); - if (line.contains(filter, Qt::CaseInsensitive)) - ui->pte_Authors->appendPlainText(line); - } - ui->pte_Authors->moveCursor(QTextCursor::Start); -} - -void AboutDialog::updateAuthors(const QString& filter) -{ - this->addAuthors(filter); } AboutDialog::~AboutDialog() @@ -384,6 +383,29 @@ AboutDialog::~AboutDialog() delete ui; } +void AboutDialog::resizeEvent(QResizeEvent * event) +{ + QList pages; + + pages << ui->tab_authors << ui->tab_folders << ui->tab_plugins << ui->tab_shortcuts; + + foreach ( QWidget * tabPage, pages ) + { + QList childs = tabPage->findChildren(); + if ( childs.count() == 0 ) + continue; + + QTableView * table = childs.at(0); + + int columnCount = table->model()->columnCount(); + for ( int cnt = 0; cnt < columnCount; cnt++ ) + table->setColumnWidth(cnt, tabPage->width() / columnCount); + table->horizontalHeader()->setStretchLastSection(true); + } + + QDialog::resizeEvent(event); +} + /* * Editor modelines * diff --git a/ui/qt/about_dialog.h b/ui/qt/about_dialog.h index 89d66f5ff7..8a1c9652f5 100644 --- a/ui/qt/about_dialog.h +++ b/ui/qt/about_dialog.h @@ -4,30 +4,80 @@ * By Gerald Combs * Copyright 1998 Gerald Combs * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * SPDX-License-Identifier: GPL-2.0+ */ #ifndef ABOUT_DIALOG_H #define ABOUT_DIALOG_H +#include "config.h" + +#include + #include +#include +#include +#include +#include +#include namespace Ui { class AboutDialog; } +class AuthorListModel : public AStringListListModel +{ +Q_OBJECT + +public: + explicit AuthorListModel(QObject * parent = Q_NULLPTR); + virtual ~AuthorListModel(); + + QString acknowledgment() const; + +protected: + virtual QStringList headerColumns() const; + +private: + QString acknowledgement_; + +}; + +class PluginListModel : public AStringListListModel +{ + Q_OBJECT +public: + explicit PluginListModel(QObject * parent = Q_NULLPTR); + + QStringList typeNames() const; + +protected: + virtual QStringList headerColumns() const; + +private: + QStringList typeNames_; +}; + +class ShortcutListModel : public AStringListListModel +{ + Q_OBJECT +public: + explicit ShortcutListModel(QObject * parent = Q_NULLPTR); + +protected: + virtual QStringList headerColumns() const; +}; + +class FolderListModel : public AStringListListModel +{ + Q_OBJECT +public: + explicit FolderListModel(QObject * parent = Q_NULLPTR); + +protected: + virtual QStringList headerColumns() const; +}; + class AboutDialog : public QDialog { Q_OBJECT @@ -36,14 +86,11 @@ public: explicit AboutDialog(QWidget *parent = 0); ~AboutDialog(); - const QString about_folders_row(const char *, const QString dir, const char *typ_file); - const QString plugins_scan(); +protected: + virtual void resizeEvent(QResizeEvent *); -public slots: - void updateAuthors(const QString&); private: Ui::AboutDialog *ui; - void addAuthors(const QString&); }; #endif // ABOUT_DIALOG_H diff --git a/ui/qt/about_dialog.ui b/ui/qt/about_dialog.ui index e517db60f3..8d029382f6 100644 --- a/ui/qt/about_dialog.ui +++ b/ui/qt/about_dialog.ui @@ -163,6 +163,13 @@ + + + + QAbstractItemView::SelectRows + + + @@ -177,6 +184,20 @@ Folders + + + + Filter by path + + + + + + + QAbstractItemView::SelectRows + + + @@ -204,12 +225,30 @@ - - - true - - - true + + + + + Search plugins + + + + + + + Filter by type: + + + + + + + + + + + + QAbstractItemView::SelectRows @@ -221,12 +260,16 @@ - - - true + + + Search Shortcuts - - true + + + + + + QAbstractItemView::SelectRows diff --git a/ui/qt/models/astringlist_list_model.cpp b/ui/qt/models/astringlist_list_model.cpp new file mode 100644 index 0000000000..61c6a6e39a --- /dev/null +++ b/ui/qt/models/astringlist_list_model.cpp @@ -0,0 +1,169 @@ +/* astringlist_list_model.cpp + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include + +#include + +AStringListListModel::AStringListListModel(QObject * parent): + QAbstractItemModel(parent) +{} + +AStringListListModel::~AStringListListModel() { modelData.clear(); } + +void AStringListListModel::appendRow(const QStringList & data, const QModelIndex &parent) +{ + QStringList columns = headerColumns(); + if ( data.count() != columns.count() ) + return; + + emit beginInsertRows(parent, rowCount(), rowCount()); + modelData << data; + emit endInsertRows(); +} + +int AStringListListModel::rowCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + + return modelData.count(); +} + +int AStringListListModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + + return headerColumns().count(); +} + +QVariant AStringListListModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if ( orientation == Qt::Vertical ) + return QVariant(); + + QStringList columns = headerColumns(); + if ( role == Qt::DisplayRole && section < columns.count() ) + return qVariantFromValue(columns[section]); + + return QVariant(); +} + +QVariant AStringListListModel::data(const QModelIndex &index, int role) const +{ + if ( role != Qt::DisplayRole || ! index.isValid() || index.row() >= rowCount() ) + return QVariant(); + + QStringList data = modelData.at(index.row()); + + if ( index.column() < columnCount() ) + return qVariantFromValue(data.at(index.column())); + + return QVariant(); +} + +QModelIndex AStringListListModel::index(int row, int column, const QModelIndex & parent) const +{ + Q_UNUSED(parent); + + if ( row >= rowCount() || column >= columnCount() ) + return QModelIndex(); + + return createIndex(row, column); +} + +QModelIndex AStringListListModel::parent(const QModelIndex & parent) const +{ + Q_UNUSED(parent); + + return QModelIndex(); +} + +AStringListListSortFilterProxyModel::AStringListListSortFilterProxyModel(QObject * parent) +: QSortFilterProxyModel(parent) +{ + filter_ = QString(); + type_ = FilterByContains; +} + +bool AStringListListSortFilterProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const +{ + QString leftData = sourceModel()->data(left).toStringList().join(","); + QString rightData = sourceModel()->data(right).toStringList().join(","); + + return QString::localeAwareCompare(leftData, rightData) < 0; +} + +void AStringListListSortFilterProxyModel::setFilter(const QString & filter) +{ + filter_ = filter; + invalidateFilter(); +} + +bool AStringListListSortFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const +{ + bool check = false; + + if ( columnsToFilter_.count() == 0 ) + return true; + + foreach(int column, columnsToFilter_) + { + if ( column >= columnCount() ) + continue; + + QModelIndex chkIdx = sourceModel()->index(sourceRow, column, sourceParent); + if ( type_ == FilterByContains && sourceModel()->data(chkIdx).toString().contains(filter_) ) + check = true; + else if ( type_ == FilterByStart && sourceModel()->data(chkIdx).toString().startsWith(filter_) ) + check = true; + + if ( check ) + break; + } + + return check; +} + +void AStringListListSortFilterProxyModel::setFilterType(AStringListListFilterType type) +{ + if ( type != type_ ) + { + type_ = type; + invalidateFilter(); + } +} + +void AStringListListSortFilterProxyModel::setColumnToFilter(int column) +{ + if ( column < columnCount() && ! columnsToFilter_.contains(column) ) + { + columnsToFilter_.append(column); + invalidateFilter(); + } +} + +void AStringListListSortFilterProxyModel::clearColumnsToFilter() +{ + columnsToFilter_.clear(); + invalidateFilter(); +} + +/* + * Editor modelines + * + * Local Variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * ex: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/ui/qt/models/astringlist_list_model.h b/ui/qt/models/astringlist_list_model.h new file mode 100644 index 0000000000..12250b1d45 --- /dev/null +++ b/ui/qt/models/astringlist_list_model.h @@ -0,0 +1,92 @@ +/* astringlist_list_model.h + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef ASTRINGLIST_LIST_MODEL_H +#define ASTRINGLIST_LIST_MODEL_H + +#include + +#include +#include +#include +#include +#include + +class AStringListListModel : public QAbstractItemModel +{ + Q_OBJECT + +public: + explicit AStringListListModel(QObject * parent = Q_NULLPTR); + virtual ~AStringListListModel(); + + virtual int rowCount(const QModelIndex &parent = QModelIndex()) const; + virtual int columnCount(const QModelIndex &parent = QModelIndex()) const; + virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + + virtual QModelIndex index(int row, int column, const QModelIndex & parent = QModelIndex()) const; + virtual QModelIndex parent(const QModelIndex & parent = QModelIndex()) const; + +protected: + virtual void appendRow(const QStringList &, const QModelIndex &parent = QModelIndex()); + + virtual QStringList headerColumns() const = 0; + +private: + QList modelData; +}; + +class AStringListListSortFilterProxyModel : public QSortFilterProxyModel +{ + Q_OBJECT +public: + + enum AStringListListFilterType + { + FilterByContains = 0, + FilterByStart = 1 + }; + + explicit AStringListListSortFilterProxyModel(QObject * parent = Q_NULLPTR); + + virtual bool lessThan(const QModelIndex &left, const QModelIndex &right) const; + virtual bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const; + + void setFilterType(AStringListListFilterType type); + + void setColumnToFilter(int); + void clearColumnsToFilter(); + +public slots: + void setFilter(const QString&); + +private: + + QString filter_; + AStringListListFilterType type_; + QList columnsToFilter_; +}; + + + +#endif // ASTRINGLIST_LIST_MODEL_H + +/* + * Editor modelines + * + * Local Variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * ex: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/ui/qt/models/html_text_delegate.cpp b/ui/qt/models/html_text_delegate.cpp new file mode 100644 index 0000000000..b906ac2d17 --- /dev/null +++ b/ui/qt/models/html_text_delegate.cpp @@ -0,0 +1,66 @@ +/* html_text_delegate.cpp + * Delegates for displaying links as links, including elide model + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +HTMLTextDelegate::HTMLTextDelegate(QObject *parent) + : QStyledItemDelegate(parent) +{} + +void HTMLTextDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { + QStyleOptionViewItem options = option; + initStyleOption(&options, index); + + painter->save(); + + QTextDocument doc; + doc.setHtml(options.text); + + options.text = QStringLiteral(""); + options.widget->style()->drawControl(QStyle::CE_ItemViewItem, &option, painter); + + painter->translate(options.rect.left(), options.rect.top()); + QRect clip(0, 0, options.rect.width(), options.rect.height()); + doc.drawContents(painter, clip); + + painter->restore(); +} + +QSize HTMLTextDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const { + QStyleOptionViewItem options = option; + initStyleOption(&options, index); + + QTextDocument doc; + doc.setHtml(options.text); + doc.setTextWidth(options.rect.width()); + return QSize(doc.idealWidth(), doc.size().height()); +} + +/* * Editor modelines + * + * Local Variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * ex: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/ui/qt/models/html_text_delegate.h b/ui/qt/models/html_text_delegate.h new file mode 100644 index 0000000000..e8e2ffd308 --- /dev/null +++ b/ui/qt/models/html_text_delegate.h @@ -0,0 +1,48 @@ +/* html_text_delegate.h + * Delegates for displaying links as links, including elide model + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef HTML_TEXT_DELEGATE_H +#define HTML_TEXT_DELEGATE_H + +#include + +#include +#include +#include +#include +#include + +class HTMLTextDelegate : public QStyledItemDelegate +{ + Q_OBJECT + +public: + explicit HTMLTextDelegate(QObject *parent = Q_NULLPTR); + +protected: + void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; + QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const; + + +}; +#endif // HTML_TEXT_DELEGATE_H + +/* + * Editor modelines + * + * Local Variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * ex: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/ui/qt/models/url_link_delegate.cpp b/ui/qt/models/url_link_delegate.cpp new file mode 100644 index 0000000000..fccb0e3071 --- /dev/null +++ b/ui/qt/models/url_link_delegate.cpp @@ -0,0 +1,68 @@ +/* url_link.cpp + * Delegates for displaying links as links, including elide model + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +UrlLinkDelegate::UrlLinkDelegate(QObject *parent) + : QStyledItemDelegate(parent) +{} + +void UrlLinkDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { + QStyleOptionViewItem options = option; + initStyleOption(&options, index); + + QString text = options.text; + if (text.isEmpty()) + return; + + int one_em = painter->fontMetrics().height(); + QString short_dir = painter->fontMetrics().elidedText(text, Qt::ElideMiddle, one_em * 10); + + painter->save(); + QFont font = option.font; + font.setUnderline(true); + painter->setFont(font); + painter->setPen(option.palette.link().color()); + painter->drawText(option.rect, Qt::AlignLeft | Qt::AlignVCenter, short_dir); + + painter->restore(); +} + +QSize UrlLinkDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const { + QStyleOptionViewItem options = option; + initStyleOption(&options, index); + + QTextDocument doc; + doc.setHtml(options.text); + doc.setTextWidth(options.rect.width()); + return QSize(doc.idealWidth(), doc.size().height()); +} + +/* * Editor modelines + * + * Local Variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * ex: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/ui/qt/models/url_link_delegate.h b/ui/qt/models/url_link_delegate.h new file mode 100644 index 0000000000..3977fbfe43 --- /dev/null +++ b/ui/qt/models/url_link_delegate.h @@ -0,0 +1,35 @@ +/* url_link_delegate.h + * Delegates for displaying links as links, including elide model + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef URL_LINK_DELEGATE_H +#define URL_LINK_DELEGATE_H + +#include + +#include +#include +#include +#include +#include + +class UrlLinkDelegate : public QStyledItemDelegate +{ + Q_OBJECT + +public: + explicit UrlLinkDelegate(QObject *parent = Q_NULLPTR); + +protected: + void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; + QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const; + + +}; +#endif // URL_LINK_DELEGATE_H