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 <rknall@gmail.com>
Tested-by: Petri Dish Buildbot
Reviewed-by: Anders Broman <a.broman58@gmail.com>
This commit is contained in:
Roland Knall 2017-11-22 16:54:32 +01:00 committed by Anders Broman
parent 8fa4a440a8
commit 73c01d6d05
11 changed files with 858 additions and 256 deletions

View File

@ -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
)

View File

@ -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 = \

View File

@ -4,19 +4,7 @@
* By Gerald Combs <gerald@wireshark.org>
* 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 <ui/qt/utils/qt_ui_utils.h>
#include <ui/qt/models/astringlist_list_model.h>
#include <ui/qt/models/url_link_delegate.h>
#include <ui/qt/models/html_text_delegate.h>
#include <QFontMetrics>
#include <QKeySequence>
#include <QTextStream>
#include <QUrl>
#include <QRegExp>
#include <QAbstractItemModel>
#include <QHash>
// 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("<tr><td>%1</td><td><a href=\"%2\">%3</a></td><td>%4</td></tr>\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<QStringList> 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("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td></tr>\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("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td></tr>\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<QString, QPair<QString, QString> > shortcuts; // name -> (shortcut, description)
foreach (const QWidget *child, wsApp->mainWindow()->findChildren<QWidget *>()) {
// 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<QString, QString>(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))
<< "<i>dfilters</i>, <i>preferences</i>, <i>ethers</i>, " UTF8_HORIZONTAL_ELLIPSIS);
/* global conf */
QString dirPath = get_datafile_dir();
if (! dirPath.isEmpty()) {
appendRow ( QStringList() << "Global configuration" << dirPath
<< "<i>dfilters</i>, <i>preferences</i>, <i>manuf</i>, " UTF8_HORIZONTAL_ELLIPSIS);
}
/* system */
appendRow( QStringList() << "System" << get_systemfile_dir() << "<i>ethers</i>, <i>ipxnets</i>");
/* 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("<table cellpadding=\"%1\">\n").arg(one_em / 4);
message += "<tr><th align=\"left\">Name</th><th align=\"left\">Location</th><th align=\"left\">Typical Files</th></tr>\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)),
"<i>dfilters</i>, <i>preferences</i>, <i>ethers</i>, " UTF8_HORIZONTAL_ELLIPSIS);
/* global conf */
constpath = get_datafile_dir();
if (constpath != NULL) {
message += about_folders_row("Global configuration", constpath,
"<i>dfilters</i>, <i>preferences</i>, <i>manuf</i>, " UTF8_HORIZONTAL_ELLIPSIS);
}
/* system */
message += about_folders_row("System", get_systemfile_dir(), "<i>ethers</i>, <i>ipxnets</i>");
/* 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 += "</table>";
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("<table cellpadding=\"%1\">\n").arg(one_em / 4);
message += "<tr><th align=\"left\">Name</th><th align=\"left\">Version</th><th align=\"left\">Type</th><th align=\"left\">Path</th></tr>\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 += "</table>";
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 = "<h3>Main Window Keyboard Shortcuts</h3>\n";
message += QString("<table cellpadding=\"%1\">\n").arg(one_em / 4);
message += "<tr><th align=\"left\">Shortcut</th><th align=\"left\">Name</th><th align=\"left\">Description</th></tr>\n";
QMap<QString, QPair<QString, QString> > shortcuts; // name -> (shortcut, description)
foreach (const QWidget *child, parent->findChildren<QWidget *>()) {
// 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<QString, QString>(action->shortcut().toString(QKeySequence::NativeText), action->toolTip());
}
}
}
QStringList names = shortcuts.keys();
names.sort();
foreach (const QString &name, names) {
message += QString("<tr><td>%1</td><td>%2</td><td>%3</td></tr>\n")
.arg(shortcuts[name].first)
.arg(name)
.arg(shortcuts[name].second);
have_shortcuts = true;
}
message += "</table>";
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<QWidget *> pages;
pages << ui->tab_authors << ui->tab_folders << ui->tab_plugins << ui->tab_shortcuts;
foreach ( QWidget * tabPage, pages )
{
QList<QTableView *> childs = tabPage->findChildren<QTableView*>();
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
*

View File

@ -4,30 +4,80 @@
* By Gerald Combs <gerald@wireshark.org>
* 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 <ui/qt/models/astringlist_list_model.h>
#include <QDialog>
#include <QAbstractItemModel>
#include <QModelIndex>
#include <QHash>
#include <QString>
#include <QSortFilterProxyModel>
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

View File

@ -163,6 +163,13 @@
</property>
</widget>
</item>
<item>
<widget class="QTableView" name="tblAuthors">
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
</widget>
</item>
<item>
<widget class="QPlainTextEdit" name="pte_Authors">
<property name="readOnly">
@ -177,6 +184,20 @@
<string>Folders</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QLineEdit" name="searchFolders">
<property name="placeholderText">
<string>Filter by path</string>
</property>
</widget>
</item>
<item>
<widget class="QTableView" name="tblFolders">
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_folders">
<property name="text">
@ -204,12 +225,30 @@
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QTextEdit" name="te_plugins">
<property name="tabChangesFocus">
<bool>true</bool>
</property>
<property name="readOnly">
<bool>true</bool>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLineEdit" name="searchPlugins">
<property name="placeholderText">
<string>Search plugins</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Filter by type:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="cmbType"/>
</item>
</layout>
</item>
<item>
<widget class="QTableView" name="tblPlugins">
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
</widget>
</item>
@ -221,12 +260,16 @@
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_shortcuts">
<item>
<widget class="QTextEdit" name="te_shortcuts">
<property name="tabChangesFocus">
<bool>true</bool>
<widget class="QLineEdit" name="searchShortcuts">
<property name="placeholderText">
<string>Search Shortcuts</string>
</property>
<property name="readOnly">
<bool>true</bool>
</widget>
</item>
<item>
<widget class="QTableView" name="tblShortcuts">
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
</widget>
</item>

View File

@ -0,0 +1,169 @@
/* astringlist_list_model.cpp
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <QSortFilterProxyModel>
#include <QStringList>
#include <ui/qt/models/astringlist_list_model.h>
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:
*/

View File

@ -0,0 +1,92 @@
/* astringlist_list_model.h
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef ASTRINGLIST_LIST_MODEL_H
#define ASTRINGLIST_LIST_MODEL_H
#include <config.h>
#include <QAbstractItemModel>
#include <QModelIndex>
#include <QList>
#include <QStringList>
#include <QSortFilterProxyModel>
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<QStringList> 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<int> 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:
*/

View File

@ -0,0 +1,66 @@
/* html_text_delegate.cpp
* Delegates for displaying links as links, including elide model
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <ui/qt/models/html_text_delegate.h>
#include <QComboBox>
#include <QEvent>
#include <QLineEdit>
#include <QPainter>
#include <QTextDocument>
#include <QRect>
#include <QStyledItemDelegate>
#include <QStyleOptionViewItem>
#include <QString>
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:
*/

View File

@ -0,0 +1,48 @@
/* html_text_delegate.h
* Delegates for displaying links as links, including elide model
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef HTML_TEXT_DELEGATE_H
#define HTML_TEXT_DELEGATE_H
#include <config.h>
#include <QWidget>
#include <QStyledItemDelegate>
#include <QStyleOptionViewItem>
#include <QModelIndex>
#include <QAbstractItemModel>
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:
*/

View File

@ -0,0 +1,68 @@
/* url_link.cpp
* Delegates for displaying links as links, including elide model
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <ui/qt/models/url_link_delegate.h>
#include <QComboBox>
#include <QEvent>
#include <QLineEdit>
#include <QPainter>
#include <QTextDocument>
#include <QRect>
#include <QStyledItemDelegate>
#include <QStyleOptionViewItem>
#include <QTextEdit>
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:
*/

View File

@ -0,0 +1,35 @@
/* url_link_delegate.h
* Delegates for displaying links as links, including elide model
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef URL_LINK_DELEGATE_H
#define URL_LINK_DELEGATE_H
#include <config.h>
#include <QWidget>
#include <QStyledItemDelegate>
#include <QStyleOptionViewItem>
#include <QModelIndex>
#include <QAbstractItemModel>
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