Qt: Move Profile Dialog to Model/View
Move the profile dialog to a model/view based concept. Display and ordering works now, but nothing much else. Add possibility to filter for profiles, as well as group filters. Change-Id: I4740ad5aa10feeb31192f8131fb1204f5dca7232 Reviewed-on: https://code.wireshark.org/review/25141 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:
parent
8bb5320cb2
commit
4e7ac431a5
|
@ -35,6 +35,7 @@ set(WIRESHARK_WIDGET_HEADERS
|
|||
widgets/overlay_scroll_bar.h
|
||||
widgets/pref_module_view.h
|
||||
widgets/packet_list_header.h
|
||||
widgets/profile_tree_view.h
|
||||
widgets/qcustomplot.h
|
||||
widgets/range_syntax_lineedit.h
|
||||
widgets/splash_overlay.h
|
||||
|
@ -89,6 +90,7 @@ set(WIRESHARK_MODEL_HEADERS
|
|||
models/percent_bar_delegate.h
|
||||
models/pref_delegate.h
|
||||
models/pref_models.h
|
||||
models/profile_model.h
|
||||
models/proto_tree_model.h
|
||||
models/related_packet_delegate.h
|
||||
models/sparkline_delegate.h
|
||||
|
@ -261,6 +263,7 @@ set(WIRESHARK_WIDGET_SRCS
|
|||
widgets/overlay_scroll_bar.cpp
|
||||
widgets/packet_list_header.cpp
|
||||
widgets/pref_module_view.cpp
|
||||
widgets/profile_tree_view.cpp
|
||||
widgets/qcustomplot.cpp
|
||||
widgets/range_syntax_lineedit.cpp
|
||||
widgets/splash_overlay.cpp
|
||||
|
@ -312,7 +315,8 @@ set(WIRESHARK_MODEL_SRCS
|
|||
models/percent_bar_delegate.cpp
|
||||
models/pref_delegate.cpp
|
||||
models/pref_models.cpp
|
||||
models/proto_tree_model.cpp
|
||||
models/profile_model.cpp
|
||||
models/proto_tree_model.cpp
|
||||
models/related_packet_delegate.cpp
|
||||
models/sparkline_delegate.cpp
|
||||
models/supported_protocols_model.cpp
|
||||
|
|
|
@ -0,0 +1,557 @@
|
|||
/* profile_model.cpp
|
||||
*
|
||||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* Copyright 1998 Gerald Combs
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
|
||||
#include "glib.h"
|
||||
#include "ui/profile.h"
|
||||
#include "wsutil/filesystem.h"
|
||||
#include "epan/prefs.h"
|
||||
|
||||
#include <ui/qt/models/profile_model.h>
|
||||
|
||||
#include <ui/qt/utils/color_utils.h>
|
||||
#include <ui/qt/utils/qt_ui_utils.h>
|
||||
|
||||
#include <QDir>
|
||||
#include <QFont>
|
||||
|
||||
#define gxx_list_next(list) ((list) ? ((reinterpret_cast<GList *>(list))->next) : Q_NULLPTR)
|
||||
|
||||
Q_LOGGING_CATEGORY(profileLogger, "wireshark.profiles")
|
||||
|
||||
ProfileSortModel::ProfileSortModel(QObject * parent):
|
||||
QSortFilterProxyModel (parent),
|
||||
ft_(ProfileSortModel::AllProfiles),
|
||||
ftext_(QString())
|
||||
{}
|
||||
|
||||
bool ProfileSortModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
|
||||
{
|
||||
QModelIndex left = source_left;
|
||||
if ( source_left.column() != ProfileModel::COL_NAME )
|
||||
left = source_left.sibling(source_left.row(), ProfileModel::COL_NAME);
|
||||
|
||||
QModelIndex right = source_right;
|
||||
if ( source_right.column() != ProfileModel::COL_NAME )
|
||||
right = source_right.sibling(source_right.row(), ProfileModel::COL_NAME);
|
||||
|
||||
bool igL = left.data(ProfileModel::DATA_IS_GLOBAL).toBool();
|
||||
bool igR = right.data(ProfileModel::DATA_IS_GLOBAL).toBool();
|
||||
|
||||
if (left.data(ProfileModel::DATA_STATUS) == PROF_STAT_DEFAULT)
|
||||
igL = true;
|
||||
if (right.data(ProfileModel::DATA_STATUS) == PROF_STAT_DEFAULT)
|
||||
igR = true;
|
||||
|
||||
if ( igL && ! igR )
|
||||
return true;
|
||||
else if ( ! igL && igR )
|
||||
return false;
|
||||
else if ( igL && igR )
|
||||
{
|
||||
if (left.data(ProfileModel::DATA_STATUS) == PROF_STAT_DEFAULT)
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( left.data().toString().compare(right.data().toString()) <= 0 )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ProfileSortModel::setFilterType(FilterType ft)
|
||||
{
|
||||
ft_ = ft;
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
void ProfileSortModel::setFilterString(QString txt)
|
||||
{
|
||||
ftext_ = ! txt.isEmpty() ? txt : "";
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
bool ProfileSortModel::filterAcceptsRow(int source_row, const QModelIndex &) const
|
||||
{
|
||||
bool accept = true;
|
||||
QModelIndex idx = sourceModel()->index(source_row, ProfileModel::COL_NAME);
|
||||
|
||||
if ( ft_ != ProfileSortModel::AllProfiles )
|
||||
{
|
||||
bool gl = idx.data(ProfileModel::DATA_IS_GLOBAL).toBool() || idx.data(ProfileModel::DATA_IS_DEFAULT).toBool();
|
||||
if ( ft_ == ProfileSortModel::UserProfiles && gl )
|
||||
accept = false;
|
||||
else if ( ft_ == ProfileSortModel::GlobalProfiles && ! gl )
|
||||
accept = false;
|
||||
}
|
||||
|
||||
if ( ftext_.length() > 0 )
|
||||
{
|
||||
QString name = idx.data().toString();
|
||||
if ( ! name.contains(ftext_, Qt::CaseInsensitive) )
|
||||
accept = false;
|
||||
}
|
||||
|
||||
return accept;
|
||||
}
|
||||
|
||||
ProfileModel::ProfileModel(QObject * parent) :
|
||||
QAbstractTableModel(parent)
|
||||
{
|
||||
/* Store preset profile name */
|
||||
set_profile_ = get_profile_name();
|
||||
|
||||
reset_default_ = false;
|
||||
|
||||
loadProfiles();
|
||||
}
|
||||
|
||||
void ProfileModel::loadProfiles()
|
||||
{
|
||||
bool refresh = profiles_.count() > 0;
|
||||
|
||||
if ( refresh )
|
||||
profiles_.clear();
|
||||
else
|
||||
init_profile_list();
|
||||
|
||||
emit beginResetModel();
|
||||
|
||||
GList *fl_entry = edited_profile_list();
|
||||
while (fl_entry && fl_entry->data)
|
||||
{
|
||||
profiles_ << reinterpret_cast<profile_def *>(fl_entry->data);
|
||||
fl_entry = gxx_list_next(fl_entry);
|
||||
}
|
||||
|
||||
emit endResetModel();
|
||||
}
|
||||
|
||||
GList * ProfileModel::entry(profile_def *ref) const
|
||||
{
|
||||
GList *fl_entry = edited_profile_list();
|
||||
while (fl_entry && fl_entry->data) {
|
||||
profile_def *profile = reinterpret_cast<profile_def *>(fl_entry->data);
|
||||
if (strcmp(ref->reference, profile->reference) == 0 && ref->is_global == profile->is_global)
|
||||
return fl_entry;
|
||||
|
||||
fl_entry = gxx_list_next(fl_entry);
|
||||
}
|
||||
|
||||
return Q_NULLPTR;
|
||||
}
|
||||
|
||||
GList *ProfileModel::at(int row) const
|
||||
{
|
||||
if ( row < 0 || row >= profiles_.count() )
|
||||
return Q_NULLPTR;
|
||||
|
||||
profile_def * prof = profiles_.at(row);
|
||||
return entry(prof);
|
||||
}
|
||||
|
||||
int ProfileModel::rowCount(const QModelIndex &) const
|
||||
{
|
||||
return profiles_.count();
|
||||
}
|
||||
|
||||
int ProfileModel::columnCount(const QModelIndex &) const
|
||||
{
|
||||
return static_cast<int>(_LAST_ENTRY);
|
||||
}
|
||||
|
||||
QVariant ProfileModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if ( ! index.isValid() || profiles_.count() <= index.row() )
|
||||
return QVariant();
|
||||
|
||||
profile_def * prof = profiles_.at(index.row());
|
||||
if ( ! prof )
|
||||
return QVariant();
|
||||
|
||||
switch ( role )
|
||||
{
|
||||
case Qt::DisplayRole:
|
||||
switch (index.column())
|
||||
{
|
||||
case COL_NAME:
|
||||
return QString(prof->name);
|
||||
case COL_TYPE:
|
||||
if ( prof->is_global || prof->status == PROF_STAT_DEFAULT )
|
||||
return tr("Global");
|
||||
else
|
||||
return tr("User");
|
||||
case COL_PATH:
|
||||
switch (prof->status)
|
||||
{
|
||||
case PROF_STAT_DEFAULT:
|
||||
if (!reset_default_)
|
||||
return get_persconffile_path("", FALSE);
|
||||
else
|
||||
return tr("Resetting to default");
|
||||
case PROF_STAT_EXISTS:
|
||||
{
|
||||
QString profile_path = prof->is_global ? get_global_profiles_dir() : get_profiles_dir();
|
||||
profile_path.append(QDir::separator()).append(prof->name);
|
||||
return profile_path;
|
||||
}
|
||||
case PROF_STAT_NEW:
|
||||
return tr("Created from default settings");
|
||||
case PROF_STAT_COPY:
|
||||
if (prof->reference)
|
||||
return QString("%1 %2").arg(tr("Copied from: ")).arg(prof->reference);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case Qt::FontRole:
|
||||
{
|
||||
QFont font;
|
||||
|
||||
if ( prof->is_global || prof->status == PROF_STAT_DEFAULT )
|
||||
font.setItalic(true);
|
||||
|
||||
if ( set_profile_.compare(prof->name) == 0 )
|
||||
{
|
||||
profile_def * act = profiles_.at(activeProfile().row());
|
||||
if ( act->is_global == prof->is_global )
|
||||
font.setBold(true);
|
||||
}
|
||||
|
||||
if ( prof->status == PROF_STAT_DEFAULT && reset_default_ )
|
||||
font.setStrikeOut(true);
|
||||
|
||||
return font;
|
||||
}
|
||||
|
||||
case Qt::BackgroundRole:
|
||||
{
|
||||
QBrush bgBrush;
|
||||
|
||||
if ( ! profile_name_is_valid(prof->name) )
|
||||
bgBrush.setColor(ColorUtils::fromColorT(&prefs.gui_text_invalid));
|
||||
|
||||
if ( prof->status == PROF_STAT_DEFAULT && reset_default_ )
|
||||
bgBrush.setColor(ColorUtils::fromColorT(&prefs.gui_text_deprecated));
|
||||
|
||||
|
||||
return bgBrush;
|
||||
}
|
||||
|
||||
case Qt::ToolTipRole:
|
||||
switch (prof->status)
|
||||
{
|
||||
case PROF_STAT_DEFAULT:
|
||||
if (reset_default_)
|
||||
return tr("Will be reset to default values");
|
||||
break;
|
||||
case PROF_STAT_COPY:
|
||||
if (prof->reference) {
|
||||
QString reference = prof->reference;
|
||||
GList *fl_entry = entry(prof);
|
||||
if (fl_entry)
|
||||
{
|
||||
profile_def *profile = reinterpret_cast<profile_def *>(fl_entry->data);
|
||||
if (strcmp(prof->reference, profile->reference) == 0) {
|
||||
if (profile->status == PROF_STAT_CHANGED) {
|
||||
// Reference profile was renamed, use the new name
|
||||
reference = profile->name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString profile_info = tr("Created from %1").arg(reference);
|
||||
if (prof->from_global) {
|
||||
profile_info.append(QString(" %1").arg(tr("(system provided)")));
|
||||
} else if (!reference.isEmpty()) {
|
||||
profile_info.append(QString(" %1").arg(tr("(deleted)")));
|
||||
}
|
||||
return profile_info;
|
||||
}
|
||||
break;
|
||||
case PROF_STAT_NEW:
|
||||
return tr("Created from default settings");
|
||||
case PROF_STAT_CHANGED:
|
||||
if ( prof->reference )
|
||||
return tr("Renamed from %1").arg(prof->reference);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (gchar * err_msg = profile_name_is_valid(prof->name))
|
||||
{
|
||||
QString msg = gchar_free_to_qstring(err_msg);
|
||||
return msg;
|
||||
}
|
||||
|
||||
if (prof->is_global)
|
||||
return tr("This is a system provided profile.");
|
||||
if ( prof->status == PROF_STAT_DEFAULT && reset_default_ )
|
||||
return tr("The profile will be reset to default values.");
|
||||
|
||||
break;
|
||||
|
||||
case ProfileModel::DATA_STATUS:
|
||||
return qVariantFromValue(prof->status);
|
||||
|
||||
case ProfileModel::DATA_IS_DEFAULT:
|
||||
return qVariantFromValue(prof->status == PROF_STAT_DEFAULT);
|
||||
|
||||
case ProfileModel::DATA_IS_GLOBAL:
|
||||
return qVariantFromValue(prof->is_global);
|
||||
|
||||
case ProfileModel::DATA_IS_SELECTED:
|
||||
{
|
||||
QModelIndex selected = activeProfile();
|
||||
profile_def * selprof = profiles_.at(selected.row());
|
||||
if ( selprof )
|
||||
{
|
||||
if ( selprof->is_global != prof->is_global )
|
||||
return qVariantFromValue(false);
|
||||
|
||||
if ( strcmp(selprof->name, prof->name) == 0 )
|
||||
return qVariantFromValue(true);
|
||||
}
|
||||
return qVariantFromValue(false);
|
||||
}
|
||||
|
||||
case ProfileModel::DATA_PATH_IS_NOT_DESCRIPTION:
|
||||
if ( prof->status == PROF_STAT_NEW || prof->status == PROF_STAT_COPY || ( prof->status == PROF_STAT_DEFAULT && reset_default_ ) )
|
||||
return qVariantFromValue(false);
|
||||
else
|
||||
return qVariantFromValue(true);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (pd_ui_->profileTreeView->topLevelItemCount() > 0) {
|
||||
profile_def *profile;
|
||||
for (int i = 0; i < pd_ui_->profileTreeView->topLevelItemCount(); i++) {
|
||||
item = pd_ui_->profileTreeView->topLevelItem(i);
|
||||
profile = (profile_def *) VariantPointer<GList>::asPtr(item->data(0, Qt::UserRole))->data;
|
||||
if (current_profile && !current_profile->is_global && profile != current_profile && strcmp(profile->name, current_profile->name) == 0) {
|
||||
item->setToolTip(0, tr("A profile already exists with this name."));
|
||||
item->setBackground(0, ColorUtils::fromColorT(&prefs.gui_text_invalid));
|
||||
if (current_profile->status != PROF_STAT_DEFAULT &&
|
||||
current_profile->status != PROF_STAT_EXISTS)
|
||||
{
|
||||
pd_ui_->infoLabel->setText(tr("A profile already exists with this name"));
|
||||
}
|
||||
enable_ok = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QVariant ProfileModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if ( orientation == Qt::Horizontal && role == Qt::DisplayRole )
|
||||
{
|
||||
switch (section)
|
||||
{
|
||||
case COL_NAME:
|
||||
return tr("Profile");
|
||||
case COL_TYPE:
|
||||
return tr("Type");
|
||||
case COL_PATH:
|
||||
return tr("Path");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
Qt::ItemFlags ProfileModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
Qt::ItemFlags fl = QAbstractTableModel::flags(index);
|
||||
|
||||
if ( ! index.isValid() || profiles_.count() <= index.row() )
|
||||
return fl;
|
||||
|
||||
profile_def * prof = profiles_.at(index.row());
|
||||
if ( ! prof )
|
||||
return fl;
|
||||
|
||||
if ( index.column() == ProfileModel::COL_NAME && ! prof->is_global && prof->status != PROF_STAT_DEFAULT )
|
||||
fl |= Qt::ItemIsEditable;
|
||||
|
||||
return fl;
|
||||
}
|
||||
|
||||
int ProfileModel::findByName(QString name)
|
||||
{
|
||||
int row = findByNameAndVisibility(name, false);
|
||||
if ( row < 0 )
|
||||
row = findByNameAndVisibility(name, true);
|
||||
|
||||
return row;
|
||||
}
|
||||
|
||||
int ProfileModel::findByNameAndVisibility(QString name, bool isGlobal)
|
||||
{
|
||||
int row = -1;
|
||||
for ( int cnt = 0; cnt < profiles_.count() && row < 0; cnt++ )
|
||||
{
|
||||
profile_def * prof = profiles_.at(cnt);
|
||||
if ( prof && prof->is_global == isGlobal && name.compare(prof->name) == 0 )
|
||||
row = cnt;
|
||||
}
|
||||
|
||||
return row;
|
||||
}
|
||||
|
||||
QModelIndex ProfileModel::addNewProfile(QString name)
|
||||
{
|
||||
add_to_profile_list(name.toUtf8().data(), "", PROF_STAT_NEW, FALSE, FALSE);
|
||||
loadProfiles();
|
||||
|
||||
return index(findByName(name), COL_NAME);
|
||||
}
|
||||
|
||||
QModelIndex ProfileModel::duplicateEntry(QModelIndex idx)
|
||||
{
|
||||
if ( ! idx.isValid() || profiles_.count() <= idx.row() )
|
||||
return QModelIndex();
|
||||
|
||||
profile_def * prof = profiles_.at(idx.row());
|
||||
if ( ! prof )
|
||||
return QModelIndex();
|
||||
|
||||
QString parent = prof->name;
|
||||
if (!prof->is_global)
|
||||
parent = get_profile_parent (prof->name);
|
||||
|
||||
QString new_name;
|
||||
if (prof->is_global && ! profile_exists (parent.toUtf8().constData(), FALSE))
|
||||
new_name = QString(prof->name);
|
||||
else
|
||||
new_name = QString("%1 (%2)").arg(parent).arg(tr("copy"));
|
||||
|
||||
if ( findByNameAndVisibility(new_name) >= 0 )
|
||||
return QModelIndex();
|
||||
|
||||
if ( new_name.compare(QString(new_name.toUtf8().constData())) != 0 && !prof->is_global )
|
||||
return QModelIndex();
|
||||
|
||||
add_to_profile_list(new_name.toUtf8().constData(), parent.toUtf8().constData(), PROF_STAT_COPY, FALSE, prof->from_global);
|
||||
loadProfiles();
|
||||
|
||||
int row = findByNameAndVisibility(new_name, false);
|
||||
if ( row < 0 || row == idx.row() )
|
||||
return QModelIndex();
|
||||
|
||||
return index(row, COL_NAME);
|
||||
}
|
||||
|
||||
void ProfileModel::deleteEntry(QModelIndex idx)
|
||||
{
|
||||
if ( ! idx.isValid() )
|
||||
return;
|
||||
|
||||
profile_def * prof = profiles_.at(idx.row());
|
||||
if ( ! prof )
|
||||
return;
|
||||
|
||||
if ( prof->is_global )
|
||||
return;
|
||||
|
||||
if ( prof->status == PROF_STAT_DEFAULT )
|
||||
{
|
||||
emit layoutAboutToBeChanged();
|
||||
reset_default_ = ! reset_default_;
|
||||
emit dataChanged(index(0, 0), index(rowCount(), columnCount()));
|
||||
emit layoutChanged();
|
||||
}
|
||||
else
|
||||
{
|
||||
GList * fl_entry = entry(prof);
|
||||
emit beginRemoveRows(QModelIndex(), idx.row(), idx.row());
|
||||
remove_from_profile_list(fl_entry);
|
||||
loadProfiles();
|
||||
emit endRemoveRows();
|
||||
}
|
||||
}
|
||||
|
||||
bool ProfileModel::resetDefault() const
|
||||
{
|
||||
return reset_default_;
|
||||
}
|
||||
|
||||
void ProfileModel::doResetModel()
|
||||
{
|
||||
reset_default_ = false;
|
||||
loadProfiles();
|
||||
}
|
||||
|
||||
QModelIndex ProfileModel::activeProfile() const
|
||||
{
|
||||
ProfileModel * temp = const_cast<ProfileModel *>(this);
|
||||
QString sel_profile = get_profile_name();
|
||||
int row = temp->findByName(sel_profile);
|
||||
if ( row >= 0 )
|
||||
return index(row, ProfileModel::COL_NAME);
|
||||
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
bool ProfileModel::setData(const QModelIndex &idx, const QVariant &value, int role)
|
||||
{
|
||||
if ( role != Qt::EditRole || ! idx.isValid() )
|
||||
return false;
|
||||
|
||||
if ( ! value.isValid() || value.toString().isEmpty() )
|
||||
return false;
|
||||
|
||||
profile_def * prof = profiles_.at(idx.row());
|
||||
if ( ! prof || prof->status == PROF_STAT_DEFAULT )
|
||||
return false;
|
||||
|
||||
QString current(prof->name);
|
||||
if ( current.compare(value.toString()) != 0 )
|
||||
{
|
||||
g_free(prof->name);
|
||||
prof->name = qstring_strdup(value.toString());
|
||||
|
||||
if (strcmp(prof->name, prof->reference) == 0) {
|
||||
prof->status = PROF_STAT_EXISTS;
|
||||
} else if (prof->status == PROF_STAT_EXISTS) {
|
||||
prof->status = PROF_STAT_CHANGED;
|
||||
}
|
||||
}
|
||||
|
||||
loadProfiles();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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:
|
||||
*/
|
|
@ -0,0 +1,118 @@
|
|||
/* profile_model.h
|
||||
*
|
||||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* Copyright 1998 Gerald Combs
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef PROFILE_MODEL_H
|
||||
#define PROFILE_MODEL_H
|
||||
|
||||
#include "glib.h"
|
||||
|
||||
#include <ui/profile.h>
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QLoggingCategory>
|
||||
|
||||
Q_DECLARE_LOGGING_CATEGORY(profileLogger);
|
||||
|
||||
class ProfileSortModel : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ProfileSortModel(QObject *parent = Q_NULLPTR);
|
||||
|
||||
enum FilterType {
|
||||
AllProfiles = 0,
|
||||
GlobalProfiles,
|
||||
UserProfiles
|
||||
};
|
||||
|
||||
void setFilterType(FilterType ft);
|
||||
void setFilterString(QString txt = QString());
|
||||
|
||||
protected:
|
||||
virtual bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const;
|
||||
virtual bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const;
|
||||
|
||||
private:
|
||||
FilterType ft_;
|
||||
QString ftext_;
|
||||
|
||||
};
|
||||
|
||||
class ProfileModel : public QAbstractTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ProfileModel(QObject * parent = Q_NULLPTR);
|
||||
|
||||
enum {
|
||||
COL_NAME,
|
||||
COL_TYPE,
|
||||
COL_PATH,
|
||||
_LAST_ENTRY
|
||||
} columns_;
|
||||
|
||||
enum {
|
||||
DATA_STATUS = Qt::UserRole,
|
||||
DATA_IS_DEFAULT,
|
||||
DATA_IS_GLOBAL,
|
||||
DATA_IS_SELECTED,
|
||||
DATA_PATH_IS_NOT_DESCRIPTION
|
||||
} data_values_;
|
||||
|
||||
// QAbstractItemModel interface
|
||||
virtual int rowCount(const QModelIndex & parent = QModelIndex()) const;
|
||||
virtual int columnCount(const QModelIndex & parent = QModelIndex()) const;
|
||||
virtual QVariant data(const QModelIndex & idx, int role = Qt::DisplayRole) const;
|
||||
virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
|
||||
virtual Qt::ItemFlags flags(const QModelIndex &index) const;
|
||||
|
||||
void deleteEntry(QModelIndex idx);
|
||||
|
||||
int findByName(QString name);
|
||||
QModelIndex addNewProfile(QString name);
|
||||
QModelIndex duplicateEntry(QModelIndex idx);
|
||||
|
||||
void doResetModel();
|
||||
bool resetDefault() const;
|
||||
|
||||
QModelIndex activeProfile() const;
|
||||
|
||||
GList * at(int row) const;
|
||||
|
||||
private:
|
||||
QList<profile_def *> profiles_;
|
||||
QString set_profile_;
|
||||
bool reset_default_;
|
||||
|
||||
void loadProfiles();
|
||||
GList * entry(profile_def *) const;
|
||||
|
||||
int findByNameAndVisibility(QString name, bool isGlobal = false);
|
||||
|
||||
// QAbstractItemModel interface
|
||||
public:
|
||||
virtual bool setData(const QModelIndex &index, const QVariant &value, int role);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 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:
|
||||
*/
|
|
@ -19,6 +19,7 @@
|
|||
#include "ui/recent.h"
|
||||
|
||||
#include <ui/qt/utils/variant_pointer.h>
|
||||
#include <ui/qt/models/profile_model.h>
|
||||
|
||||
#include "profile_dialog.h"
|
||||
#include <ui_profile_dialog.h>
|
||||
|
@ -32,19 +33,20 @@
|
|||
#include <QPushButton>
|
||||
#include <QTreeWidgetItem>
|
||||
#include <QUrl>
|
||||
#include <QComboBox>
|
||||
#include <QLineEdit>
|
||||
|
||||
ProfileDialog::ProfileDialog(QWidget *parent) :
|
||||
GeometryStateDialog(parent),
|
||||
pd_ui_(new Ui::ProfileDialog),
|
||||
ok_button_(NULL)
|
||||
ok_button_(Q_NULLPTR),
|
||||
model_(Q_NULLPTR),
|
||||
sort_model_(Q_NULLPTR)
|
||||
{
|
||||
GList *fl_entry;
|
||||
profile_def *profile;
|
||||
const gchar *profile_name = get_profile_name();
|
||||
|
||||
pd_ui_->setupUi(this);
|
||||
loadGeometry();
|
||||
setWindowTitle(wsApp->windowTitleString(tr("Configuration Profiles")));
|
||||
|
||||
ok_button_ = pd_ui_->buttonBox->button(QDialogButtonBox::Ok);
|
||||
|
||||
// XXX - Use NSImageNameAddTemplate and NSImageNameRemoveTemplate to set stock
|
||||
|
@ -60,33 +62,29 @@ ProfileDialog::ProfileDialog(QWidget *parent) :
|
|||
pd_ui_->infoLabel->setAttribute(Qt::WA_MacSmallSize, true);
|
||||
#endif
|
||||
|
||||
init_profile_list();
|
||||
fl_entry = edited_profile_list();
|
||||
pd_ui_->profileTreeWidget->blockSignals(true);
|
||||
while (fl_entry && fl_entry->data) {
|
||||
profile = (profile_def *) fl_entry->data;
|
||||
QTreeWidgetItem *item = new QTreeWidgetItem(pd_ui_->profileTreeWidget);
|
||||
item->setText(0, profile->name);
|
||||
item->setData(0, Qt::UserRole, VariantPointer<GList>::asQVariant(fl_entry));
|
||||
model_ = new ProfileModel(this);
|
||||
sort_model_ = new ProfileSortModel(this);
|
||||
sort_model_->setSourceModel(model_);
|
||||
pd_ui_->profileTreeView->setModel(sort_model_);
|
||||
|
||||
if (profile->is_global || profile->status == PROF_STAT_DEFAULT) {
|
||||
QFont ti_font = item->font(0);
|
||||
ti_font.setItalic(true);
|
||||
item->setFont(0, ti_font);
|
||||
} else {
|
||||
item->setFlags(item->flags() | Qt::ItemIsEditable);
|
||||
}
|
||||
connect(pd_ui_->profileTreeView, &ProfileTreeView::currentItemChanged,
|
||||
this, &ProfileDialog::currentItemChanged);
|
||||
|
||||
if (!profile->is_global && strcmp(profile_name, profile->name) == 0) {
|
||||
pd_ui_->profileTreeWidget->setCurrentItem(item);
|
||||
}
|
||||
|
||||
fl_entry = g_list_next(fl_entry);
|
||||
}
|
||||
pd_ui_->profileTreeWidget->blockSignals(false);
|
||||
|
||||
connect(pd_ui_->profileTreeWidget->itemDelegate(), SIGNAL(closeEditor(QWidget*, QAbstractItemDelegate::EndEditHint)),
|
||||
connect(pd_ui_->profileTreeView->itemDelegate(), SIGNAL(closeEditor(QWidget*, QAbstractItemDelegate::EndEditHint)),
|
||||
this, SLOT(editingFinished()));
|
||||
|
||||
/* Select the row for the currently selected profile or the first row if non is selected*/
|
||||
selectProfile();
|
||||
|
||||
QStringList items;
|
||||
items << tr("All Profiles") << tr("Global profiles") << tr("User-defined profiles");
|
||||
pd_ui_->cmbProfileTypes->addItems(items);
|
||||
|
||||
connect (pd_ui_->cmbProfileTypes, SIGNAL(currentTextChanged(const QString &)),
|
||||
this, SLOT(filterChanged(const QString &)));
|
||||
connect (pd_ui_->lineProfileFilter, SIGNAL(textChanged(const QString &)),
|
||||
this, SLOT(filterChanged(const QString &)));
|
||||
|
||||
updateWidgets();
|
||||
}
|
||||
|
||||
|
@ -96,10 +94,21 @@ ProfileDialog::~ProfileDialog()
|
|||
empty_profile_list (TRUE);
|
||||
}
|
||||
|
||||
void ProfileDialog::selectProfile(QString profile)
|
||||
{
|
||||
if ( profile.isEmpty() )
|
||||
profile = QString(get_profile_name());
|
||||
|
||||
int row = model_->findByName(profile);
|
||||
QModelIndex idx = sort_model_->mapFromSource(model_->index(row, ProfileModel::COL_NAME));
|
||||
if ( idx.isValid() )
|
||||
pd_ui_->profileTreeView->selectRow(idx.row());
|
||||
}
|
||||
|
||||
int ProfileDialog::execAction(ProfileDialog::ProfileAction profile_action)
|
||||
{
|
||||
int ret = QDialog::Accepted;
|
||||
QTreeWidgetItem *item;
|
||||
QModelIndex item;
|
||||
|
||||
switch (profile_action) {
|
||||
case ShowProfiles:
|
||||
|
@ -110,259 +119,134 @@ int ProfileDialog::execAction(ProfileDialog::ProfileAction profile_action)
|
|||
ret = exec();
|
||||
break;
|
||||
case EditCurrentProfile:
|
||||
item = pd_ui_->profileTreeWidget->currentItem();
|
||||
if (item) {
|
||||
pd_ui_->profileTreeWidget->editItem(item, 0);
|
||||
item = pd_ui_->profileTreeView->currentIndex();
|
||||
if (item.isValid()) {
|
||||
pd_ui_->profileTreeView->edit(item);
|
||||
}
|
||||
ret = exec();
|
||||
break;
|
||||
case DeleteCurrentProfile:
|
||||
if (delete_current_profile()) {
|
||||
wsApp->setConfigurationProfile (NULL);
|
||||
wsApp->setConfigurationProfile (Q_NULLPTR);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ProfileDialog::updateWidgets()
|
||||
{
|
||||
QTreeWidgetItem *item = pd_ui_->profileTreeWidget->currentItem();
|
||||
bool enable_new = false;
|
||||
bool enable_del = false;
|
||||
bool enable_copy = false;
|
||||
bool enable_ok = true;
|
||||
profile_def *current_profile = NULL;
|
||||
|
||||
if (item) {
|
||||
current_profile = (profile_def *) VariantPointer<GList>::asPtr(item->data(0, Qt::UserRole))->data;
|
||||
enable_new = true;
|
||||
enable_copy = true;
|
||||
if (!current_profile->is_global && !(item->font(0).strikeOut())) {
|
||||
QModelIndex index = sort_model_->mapToSource(pd_ui_->profileTreeView->currentIndex());
|
||||
if ( index.column() != ProfileModel::COL_NAME )
|
||||
index = index.sibling(index.row(), ProfileModel::COL_NAME);
|
||||
|
||||
if (index.isValid()) {
|
||||
if ( !index.data(ProfileModel::DATA_IS_GLOBAL).toBool() && ! model_->resetDefault())
|
||||
enable_del = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (current_profile) {
|
||||
QString profile_path;
|
||||
QString profile_info;
|
||||
switch (current_profile->status) {
|
||||
case PROF_STAT_DEFAULT:
|
||||
if (item->font(0).strikeOut()) {
|
||||
profile_info = tr("Will be reset to default values");
|
||||
} else {
|
||||
profile_path = get_persconffile_path("", FALSE);
|
||||
}
|
||||
break;
|
||||
case PROF_STAT_EXISTS:
|
||||
if (model_ && model_->rowCount() > 0)
|
||||
{
|
||||
for ( int row = 0; row < model_->rowCount(); row++ )
|
||||
{
|
||||
QModelIndex idx = model_->index(row, ProfileModel::COL_NAME);
|
||||
QString name = idx.data().toString();
|
||||
|
||||
if (gchar * err_msg = profile_name_is_valid(name.toLatin1().data()))
|
||||
{
|
||||
char* profile_dir = current_profile->is_global ? get_global_profiles_dir() : get_profiles_dir();
|
||||
profile_path = profile_dir;
|
||||
g_free(profile_dir);
|
||||
|
||||
profile_path.append(QDir::separator()).append(current_profile->name);
|
||||
}
|
||||
break;
|
||||
case PROF_STAT_COPY:
|
||||
if (current_profile->reference) {
|
||||
bool reference_exists = false;
|
||||
gchar *reference = current_profile->reference;
|
||||
GList *fl_entry = edited_profile_list();
|
||||
while (fl_entry && fl_entry->data) {
|
||||
profile_def *profile = (profile_def *) fl_entry->data;
|
||||
if (strcmp(current_profile->reference, profile->reference) == 0) {
|
||||
if (profile->status != PROF_STAT_COPY) {
|
||||
// Reference profile exists (and is not current profile)
|
||||
reference_exists = true;
|
||||
}
|
||||
if (profile->status == PROF_STAT_CHANGED) {
|
||||
// Reference profile was renamed, use the new name
|
||||
reference = profile->name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fl_entry = g_list_next(fl_entry);
|
||||
}
|
||||
profile_info = tr("Created from %1").arg(reference);
|
||||
if (current_profile->from_global) {
|
||||
profile_info.append(QString(" %1").arg(tr("(system provided)")));
|
||||
} else if (!reference_exists) {
|
||||
profile_info.append(QString(" %1").arg(tr("(deleted)")));
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* Fall Through */
|
||||
case PROF_STAT_NEW:
|
||||
profile_info = tr("Created from default settings");
|
||||
break;
|
||||
case PROF_STAT_CHANGED:
|
||||
profile_info = tr("Renamed from %1").arg(current_profile->reference);
|
||||
break;
|
||||
}
|
||||
if (!profile_path.isEmpty()) {
|
||||
pd_ui_->infoLabel->setUrl(QUrl::fromLocalFile(profile_path).toString());
|
||||
pd_ui_->infoLabel->setText(profile_path);
|
||||
pd_ui_->infoLabel->setToolTip(tr("Go to %1").arg(profile_path));
|
||||
} else {
|
||||
pd_ui_->infoLabel->clear();
|
||||
pd_ui_->infoLabel->setText(profile_info);
|
||||
}
|
||||
} else {
|
||||
pd_ui_->infoLabel->clear();
|
||||
}
|
||||
|
||||
if (pd_ui_->profileTreeWidget->topLevelItemCount() > 0) {
|
||||
profile_def *profile;
|
||||
for (int i = 0; i < pd_ui_->profileTreeWidget->topLevelItemCount(); i++) {
|
||||
item = pd_ui_->profileTreeWidget->topLevelItem(i);
|
||||
profile = (profile_def *) VariantPointer<GList>::asPtr(item->data(0, Qt::UserRole))->data;
|
||||
if (gchar *err_msg = profile_name_is_valid(profile->name)) {
|
||||
item->setToolTip(0, err_msg);
|
||||
item->setBackground(0, ColorUtils::fromColorT(&prefs.gui_text_invalid));
|
||||
if (profile == current_profile) {
|
||||
pd_ui_->infoLabel->setText(err_msg);
|
||||
}
|
||||
g_free(err_msg);
|
||||
pd_ui_->infoLabel->setText(gchar_free_to_qstring(err_msg));
|
||||
enable_ok = false;
|
||||
continue;
|
||||
}
|
||||
if (profile->is_global) {
|
||||
item->setToolTip(0, tr("This is a system provided profile."));
|
||||
continue;
|
||||
}
|
||||
if (current_profile && !current_profile->is_global && profile != current_profile && strcmp(profile->name, current_profile->name) == 0) {
|
||||
item->setToolTip(0, tr("A profile already exists with this name."));
|
||||
item->setBackground(0, ColorUtils::fromColorT(&prefs.gui_text_invalid));
|
||||
if (current_profile->status != PROF_STAT_DEFAULT &&
|
||||
current_profile->status != PROF_STAT_EXISTS)
|
||||
|
||||
if ( idx != index && idx.data().toString().compare(index.data().toString()) == 0 )
|
||||
{
|
||||
if (idx.data(ProfileModel::DATA_IS_GLOBAL).toBool() == index.data(ProfileModel::DATA_IS_GLOBAL).toBool())
|
||||
{
|
||||
pd_ui_->infoLabel->setText(tr("A profile already exists with this name"));
|
||||
int status = index.data(ProfileModel::DATA_STATUS).toInt();
|
||||
if (status != PROF_STAT_DEFAULT && status != PROF_STAT_EXISTS)
|
||||
pd_ui_->infoLabel->setText(tr("A profile already exists with this name"));
|
||||
enable_ok = false;
|
||||
}
|
||||
enable_ok = false;
|
||||
} else if (item->font(0).strikeOut()) {
|
||||
item->setToolTip(0, tr("The profile will be reset to default values."));
|
||||
item->setBackground(0, ColorUtils::fromColorT(&prefs.gui_text_deprecated));
|
||||
} else {
|
||||
item->setBackground(0, QBrush());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pd_ui_->profileTreeWidget->resizeColumnToContents(0);
|
||||
pd_ui_->newToolButton->setEnabled(enable_new);
|
||||
pd_ui_->profileTreeView->resizeColumnToContents(0);
|
||||
pd_ui_->deleteToolButton->setEnabled(enable_del);
|
||||
pd_ui_->copyToolButton->setEnabled(enable_copy);
|
||||
ok_button_->setEnabled(enable_ok);
|
||||
}
|
||||
|
||||
void ProfileDialog::on_profileTreeWidget_currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)
|
||||
void ProfileDialog::currentItemChanged()
|
||||
{
|
||||
if (pd_ui_->profileTreeWidget->updatesEnabled()) updateWidgets();
|
||||
updateWidgets();
|
||||
}
|
||||
|
||||
void ProfileDialog::on_newToolButton_clicked()
|
||||
{
|
||||
QTreeWidgetItem *item = new QTreeWidgetItem();
|
||||
profile_def *profile;
|
||||
const gchar *name = "New profile";
|
||||
GList *fl_entry = add_to_profile_list(name, "", PROF_STAT_NEW, FALSE, FALSE);
|
||||
if ( model_->findByName(tr("New profile")) >= 0 )
|
||||
return;
|
||||
|
||||
profile = (profile_def *) fl_entry->data;
|
||||
item->setText(0, profile->name);
|
||||
item->setData(0, Qt::UserRole, VariantPointer<GList>::asQVariant(fl_entry));
|
||||
item->setFlags(item->flags() | Qt::ItemIsEditable);
|
||||
pd_ui_->profileTreeWidget->addTopLevelItem(item);
|
||||
pd_ui_->profileTreeWidget->setCurrentItem(item);
|
||||
pd_ui_->profileTreeWidget->editItem(item, 0);
|
||||
pd_ui_->cmbProfileTypes->setCurrentIndex(ProfileSortModel::UserProfiles);
|
||||
sort_model_->setFilterString();
|
||||
|
||||
QModelIndex ridx = sort_model_->mapFromSource(model_->addNewProfile(tr("New profile")));
|
||||
if (ridx.isValid())
|
||||
{
|
||||
pd_ui_->profileTreeView->setCurrentIndex(ridx);
|
||||
pd_ui_->profileTreeView->edit(ridx);
|
||||
}
|
||||
}
|
||||
|
||||
void ProfileDialog::on_deleteToolButton_clicked()
|
||||
{
|
||||
QTreeWidgetItem *item = pd_ui_->profileTreeWidget->currentItem();
|
||||
QModelIndex index = sort_model_->mapToSource(pd_ui_->profileTreeView->currentIndex());
|
||||
|
||||
if (item) {
|
||||
GList *fl_entry = VariantPointer<GList>::asPtr(item->data(0, Qt::UserRole));
|
||||
profile_def *profile = (profile_def *) fl_entry->data;
|
||||
if (profile->is_global || item->font(0).strikeOut()) {
|
||||
return;
|
||||
}
|
||||
if (profile->status == PROF_STAT_DEFAULT) {
|
||||
QFont ti_font = item->font(0);
|
||||
ti_font.setStrikeOut(true);
|
||||
item->setFont(0, ti_font);
|
||||
updateWidgets();
|
||||
} else {
|
||||
delete item;
|
||||
|
||||
// Select the default
|
||||
pd_ui_->profileTreeWidget->setCurrentItem(pd_ui_->profileTreeWidget->topLevelItem(0));
|
||||
|
||||
remove_from_profile_list(fl_entry);
|
||||
}
|
||||
}
|
||||
model_->deleteEntry(index);
|
||||
}
|
||||
|
||||
void ProfileDialog::on_copyToolButton_clicked()
|
||||
{
|
||||
QTreeWidgetItem *cur_item = pd_ui_->profileTreeWidget->currentItem();
|
||||
if (!cur_item) return;
|
||||
pd_ui_->cmbProfileTypes->setCurrentIndex(ProfileSortModel::AllProfiles);
|
||||
sort_model_->setFilterString();
|
||||
|
||||
profile_def *cur_profile = (profile_def *) VariantPointer<GList>::asPtr(cur_item->data(0, Qt::UserRole))->data;
|
||||
if (!cur_profile) return;
|
||||
QModelIndex current = pd_ui_->profileTreeView->currentIndex();
|
||||
if ( current.column() != ProfileModel::COL_NAME )
|
||||
current = current.sibling(current.row(), ProfileModel::COL_NAME);
|
||||
|
||||
QTreeWidgetItem *new_item = new QTreeWidgetItem();
|
||||
GList *fl_entry;
|
||||
const gchar *parent;
|
||||
gchar *new_name;
|
||||
profile_def *new_profile;
|
||||
|
||||
if (cur_profile->is_global) {
|
||||
parent = cur_profile->name;
|
||||
} else {
|
||||
parent = get_profile_parent (cur_profile->name);
|
||||
QModelIndex source = sort_model_->mapToSource(current);
|
||||
QModelIndex ridx = model_->duplicateEntry(source);
|
||||
if (ridx.isValid())
|
||||
{
|
||||
pd_ui_->profileTreeView->setCurrentIndex(sort_model_->mapFromSource(ridx));
|
||||
pd_ui_->profileTreeView->edit(sort_model_->mapFromSource(ridx));
|
||||
}
|
||||
|
||||
if (cur_profile->is_global && !profile_exists (parent, FALSE)) {
|
||||
new_name = g_strdup (cur_profile->name);
|
||||
} else {
|
||||
new_name = g_strdup_printf ("%s (copy)", cur_profile->name);
|
||||
}
|
||||
|
||||
/* Add a new entry to the profile list. */
|
||||
fl_entry = add_to_profile_list(new_name, parent, PROF_STAT_COPY, FALSE, cur_profile->from_global);
|
||||
new_profile = (profile_def *) fl_entry->data;
|
||||
new_item->setText(0, new_profile->name);
|
||||
new_item->setData(0, Qt::UserRole, VariantPointer<GList>::asQVariant(fl_entry));
|
||||
new_item->setFlags(new_item->flags() | Qt::ItemIsEditable);
|
||||
pd_ui_->profileTreeWidget->addTopLevelItem(new_item);
|
||||
pd_ui_->profileTreeWidget->setCurrentItem(new_item);
|
||||
pd_ui_->profileTreeWidget->editItem(new_item, 0);
|
||||
g_free(new_name);
|
||||
}
|
||||
|
||||
void ProfileDialog::on_buttonBox_accepted()
|
||||
{
|
||||
gchar *err_msg;
|
||||
QTreeWidgetItem *default_item = pd_ui_->profileTreeWidget->topLevelItem(0);
|
||||
QTreeWidgetItem *item = pd_ui_->profileTreeWidget->currentItem();
|
||||
gchar *profile_name = NULL;
|
||||
QModelIndex default_item = sort_model_->mapFromSource(model_->index(0, ProfileModel::COL_NAME));
|
||||
QModelIndex index = sort_model_->mapToSource(pd_ui_->profileTreeView->currentIndex());
|
||||
if (index.column() != ProfileModel::COL_NAME)
|
||||
index = index.sibling(index.row(), ProfileModel::COL_NAME);
|
||||
|
||||
bool write_recent = true;
|
||||
bool item_data_removed = false;
|
||||
|
||||
if (default_item && default_item->font(0).strikeOut()) {
|
||||
if (default_item.data(ProfileModel::DATA_STATUS).toInt() == PROF_STAT_DEFAULT && model_->resetDefault())
|
||||
{
|
||||
// Reset Default profile.
|
||||
GList *fl_entry = VariantPointer<GList>::asPtr(default_item->data(0, Qt::UserRole));
|
||||
GList *fl_entry = model_->at(0);
|
||||
remove_from_profile_list(fl_entry);
|
||||
|
||||
// Don't write recent file if leaving the Default profile after this has been reset.
|
||||
write_recent = !is_default_profile();
|
||||
|
||||
// Don't fetch profile data if removed.
|
||||
item_data_removed = (item == default_item);
|
||||
item_data_removed = (index.row() == 0);
|
||||
}
|
||||
|
||||
if (write_recent) {
|
||||
|
@ -374,17 +258,23 @@ void ProfileDialog::on_buttonBox_accepted()
|
|||
write_profile_recent();
|
||||
}
|
||||
|
||||
if ((err_msg = apply_profile_changes()) != NULL) {
|
||||
gchar * err_msg = Q_NULLPTR;
|
||||
if ((err_msg = apply_profile_changes()) != Q_NULLPTR) {
|
||||
QMessageBox::critical(this, tr("Profile Error"),
|
||||
err_msg,
|
||||
QMessageBox::Ok);
|
||||
g_free(err_msg);
|
||||
|
||||
model_->doResetModel();
|
||||
return;
|
||||
}
|
||||
|
||||
if (item && !item_data_removed) {
|
||||
profile_def *profile = (profile_def *) VariantPointer<GList>::asPtr(item->data(0, Qt::UserRole))->data;
|
||||
profile_name = profile->name;
|
||||
model_->doResetModel();
|
||||
|
||||
const char * profile_name = Q_NULLPTR;
|
||||
if (index.isValid() && !item_data_removed) {
|
||||
QString profileName = model_->data(index).toString();
|
||||
profile_name = profileName.toLatin1().data();
|
||||
}
|
||||
|
||||
if (profile_exists (profile_name, FALSE) || profile_exists (profile_name, TRUE)) {
|
||||
|
@ -393,7 +283,7 @@ void ProfileDialog::on_buttonBox_accepted()
|
|||
} else if (!profile_exists (get_profile_name(), FALSE)) {
|
||||
// The new profile does not exist, and the previous profile has
|
||||
// been deleted. Change to the default profile.
|
||||
wsApp->setConfigurationProfile (NULL, FALSE);
|
||||
wsApp->setConfigurationProfile (Q_NULLPTR, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -404,23 +294,26 @@ void ProfileDialog::on_buttonBox_helpRequested()
|
|||
|
||||
void ProfileDialog::editingFinished()
|
||||
{
|
||||
QTreeWidgetItem *item = pd_ui_->profileTreeWidget->currentItem();
|
||||
|
||||
if (item) {
|
||||
profile_def *profile = (profile_def *) VariantPointer<GList>::asPtr(item->data(0, Qt::UserRole))->data;
|
||||
if (item->text(0).compare(profile->name) != 0) {
|
||||
g_free(profile->name);
|
||||
profile->name = qstring_strdup(item->text(0));
|
||||
if (strcmp(profile->name, profile->reference) == 0) {
|
||||
profile->status = PROF_STAT_EXISTS;
|
||||
} else if (profile->status == PROF_STAT_EXISTS) {
|
||||
profile->status = PROF_STAT_CHANGED;
|
||||
}
|
||||
}
|
||||
}
|
||||
updateWidgets();
|
||||
}
|
||||
|
||||
void ProfileDialog::filterChanged(const QString &text)
|
||||
{
|
||||
if (qobject_cast<QComboBox *>(sender()))
|
||||
{
|
||||
QComboBox * cmb = qobject_cast<QComboBox *>(sender());
|
||||
sort_model_->setFilterType(static_cast<ProfileSortModel::FilterType>(cmb->currentIndex()));
|
||||
}
|
||||
else if (qobject_cast<QLineEdit *>(sender()))
|
||||
sort_model_->setFilterString(text);
|
||||
|
||||
pd_ui_->profileTreeView->resizeColumnToContents(ProfileModel::COL_NAME);
|
||||
|
||||
QModelIndex active = sort_model_->mapFromSource(model_->activeProfile());
|
||||
if (active.isValid())
|
||||
pd_ui_->profileTreeView->setCurrentIndex(active);
|
||||
}
|
||||
|
||||
/*
|
||||
* Editor modelines
|
||||
*
|
||||
|
|
|
@ -10,10 +10,12 @@
|
|||
#ifndef PROFILE_DIALOG_H
|
||||
#define PROFILE_DIALOG_H
|
||||
|
||||
#include "geometry_state_dialog.h"
|
||||
#include <ui/qt/geometry_state_dialog.h>
|
||||
#include <ui/qt/models/profile_model.h>
|
||||
#include <ui/qt/widgets/profile_tree_view.h>
|
||||
|
||||
class QPushButton;
|
||||
class QTreeWidgetItem;
|
||||
#include <QPushButton>
|
||||
#include <QTreeWidgetItem>
|
||||
|
||||
namespace Ui {
|
||||
class ProfileDialog;
|
||||
|
@ -26,24 +28,39 @@ class ProfileDialog : public GeometryStateDialog
|
|||
public:
|
||||
enum ProfileAction { ShowProfiles, NewProfile, EditCurrentProfile, DeleteCurrentProfile };
|
||||
|
||||
explicit ProfileDialog(QWidget *parent = 0);
|
||||
explicit ProfileDialog(QWidget *parent = Q_NULLPTR);
|
||||
~ProfileDialog();
|
||||
int execAction(ProfileAction profile_action);
|
||||
|
||||
/**
|
||||
* @brief Select the profile with the given name.
|
||||
*
|
||||
* If the profile name is empty, the currently selected profile will be choosen instead.
|
||||
* If the choosen profile is invalid, the first row will be choosen.
|
||||
*
|
||||
* @param profile the name of the profile to be selected
|
||||
*/
|
||||
void selectProfile(QString profile = QString());
|
||||
|
||||
private:
|
||||
void updateWidgets();
|
||||
Ui::ProfileDialog *pd_ui_;
|
||||
QPushButton *ok_button_;
|
||||
ProfileModel *model_;
|
||||
ProfileSortModel *sort_model_;
|
||||
|
||||
void updateWidgets();
|
||||
|
||||
private slots:
|
||||
void on_profileTreeWidget_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous);
|
||||
void currentItemChanged();
|
||||
|
||||
void on_newToolButton_clicked();
|
||||
void on_deleteToolButton_clicked();
|
||||
void on_copyToolButton_clicked();
|
||||
void on_buttonBox_accepted();
|
||||
void on_buttonBox_helpRequested();
|
||||
void editingFinished();
|
||||
|
||||
void filterChanged(const QString &);
|
||||
};
|
||||
|
||||
#endif // PROFILE_DIALOG_H
|
||||
|
|
|
@ -7,12 +7,26 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>470</width>
|
||||
<height>300</height>
|
||||
<height>386</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QTreeWidget" name="profileTreeWidget">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="lineProfileFilter">
|
||||
<property name="placeholderText">
|
||||
<string>Search for profile ...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="cmbProfileTypes"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="ProfileTreeView" name="profileTreeView">
|
||||
<property name="rootIsDecorated">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
|
@ -22,24 +36,22 @@
|
|||
<property name="itemsExpandable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="headerHidden">
|
||||
<bool>true</bool>
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="expandsOnDoubleClick">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="columnCount">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Name</string>
|
||||
</property>
|
||||
</column>
|
||||
<attribute name="headerVisible">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,0,0,0,1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,0,0,0,0">
|
||||
<item>
|
||||
<widget class="StockIconToolButton" name="newToolButton">
|
||||
<property name="toolTip">
|
||||
|
@ -124,6 +136,11 @@
|
|||
<extends>QToolButton</extends>
|
||||
<header>widgets/stock_icon_tool_button.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>ProfileTreeView</class>
|
||||
<extends>QTreeView</extends>
|
||||
<header>widgets/profile_tree_view.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections>
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
/* profile_tree_view.cpp
|
||||
*
|
||||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* Copyright 1998 Gerald Combs
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include <ui/qt/models/url_link_delegate.h>
|
||||
#include <ui/qt/models/profile_model.h>
|
||||
#include <ui/qt/widgets/profile_tree_view.h>
|
||||
|
||||
#include <QDesktopServices>
|
||||
#include <QDir>
|
||||
#include <QItemDelegate>
|
||||
#include <QLineEdit>
|
||||
#include <QUrl>
|
||||
|
||||
ProfileUrlLinkDelegate::ProfileUrlLinkDelegate(QObject *parent) : UrlLinkDelegate (parent) {}
|
||||
|
||||
void ProfileUrlLinkDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
{
|
||||
if ( index.column() != ProfileModel::COL_PATH )
|
||||
QStyledItemDelegate::paint(painter, option, index);
|
||||
|
||||
/* Only paint links for valid paths */
|
||||
if ( index.data(ProfileModel::DATA_PATH_IS_NOT_DESCRIPTION).toBool() )
|
||||
UrlLinkDelegate::paint(painter, option, index);
|
||||
else
|
||||
QStyledItemDelegate::paint(painter, option, index);
|
||||
|
||||
}
|
||||
|
||||
ProfileTreeEditDelegate::ProfileTreeEditDelegate(QWidget *parent) : QItemDelegate(parent) {}
|
||||
|
||||
void ProfileTreeEditDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
|
||||
{
|
||||
if (qobject_cast<QLineEdit *>(editor))
|
||||
{
|
||||
QLineEdit * ql = qobject_cast<QLineEdit *>(editor);
|
||||
ql->setText(index.data().toString());
|
||||
}
|
||||
}
|
||||
|
||||
ProfileTreeView::ProfileTreeView(QWidget *parent) :
|
||||
QTreeView (parent)
|
||||
{
|
||||
setItemDelegateForColumn(ProfileModel::COL_NAME, new ProfileTreeEditDelegate());
|
||||
setItemDelegateForColumn(ProfileModel::COL_PATH, new ProfileUrlLinkDelegate());
|
||||
|
||||
resizeColumnToContents(ProfileModel::COL_NAME);
|
||||
|
||||
connect(this, &QAbstractItemView::clicked, this, &ProfileTreeView::clicked);
|
||||
}
|
||||
|
||||
void ProfileTreeView::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
|
||||
{
|
||||
if ( selected.count() == 0 && deselected.count() > 0 )
|
||||
{
|
||||
QItemSelection newSelection;
|
||||
newSelection << deselected.at(0);
|
||||
selectionModel()->select(newSelection, QItemSelectionModel::ClearAndSelect);
|
||||
}
|
||||
else if ( selected.count() > 1 )
|
||||
{
|
||||
/* If more then one item is selected, only accept the new item, deselect everything else */
|
||||
QSet<QItemSelectionRange> intersection = selected.toSet().intersect(deselected.toSet());
|
||||
QItemSelection newSelection;
|
||||
newSelection << intersection.toList().at(0);
|
||||
selectionModel()->select(newSelection, QItemSelectionModel::ClearAndSelect);
|
||||
}
|
||||
else
|
||||
QTreeView::selectionChanged(selected, deselected);
|
||||
}
|
||||
|
||||
void ProfileTreeView::currentChanged(const QModelIndex &, const QModelIndex &)
|
||||
{
|
||||
emit currentItemChanged();
|
||||
}
|
||||
|
||||
void ProfileTreeView::clicked(const QModelIndex &index)
|
||||
{
|
||||
if ( !index.isValid() || index.column() != ProfileModel::COL_PATH )
|
||||
return;
|
||||
|
||||
/* Only paint links for valid paths */
|
||||
if ( index.data(ProfileModel::DATA_PATH_IS_NOT_DESCRIPTION).toBool() )
|
||||
{
|
||||
QString path = QDir::toNativeSeparators(index.data().toString());
|
||||
QDesktopServices::openUrl(QUrl::fromLocalFile(path));
|
||||
}
|
||||
}
|
||||
|
||||
void ProfileTreeView::selectRow(int row)
|
||||
{
|
||||
if ( row < 0 )
|
||||
return;
|
||||
|
||||
setCurrentIndex(model()->index(row, 0));
|
||||
|
||||
selectionModel()->select(
|
||||
QItemSelection(model()->index(row, 0), model()->index(row, model()->columnCount() -1)),
|
||||
QItemSelectionModel::ClearAndSelect);
|
||||
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/* profile_tree_view.h
|
||||
*
|
||||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* Copyright 1998 Gerald Combs
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef PROFILE_TREEVIEW_H
|
||||
#define PROFILE_TREEVIEW_H
|
||||
|
||||
#include <ui/qt/models/url_link_delegate.h>
|
||||
|
||||
#include <QTreeView>
|
||||
#include <QItemDelegate>
|
||||
|
||||
class ProfileUrlLinkDelegate : public UrlLinkDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ProfileUrlLinkDelegate(QObject *parent = Q_NULLPTR);
|
||||
|
||||
virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
|
||||
};
|
||||
|
||||
class ProfileTreeEditDelegate : public QItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ProfileTreeEditDelegate(QWidget *parent = Q_NULLPTR);
|
||||
|
||||
virtual void setEditorData(QWidget *editor, const QModelIndex &index) const;
|
||||
};
|
||||
|
||||
class ProfileTreeView : public QTreeView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ProfileTreeView(QWidget *parent = nullptr);
|
||||
|
||||
void selectRow(int row);
|
||||
|
||||
Q_SIGNALS:
|
||||
void currentItemChanged();
|
||||
|
||||
// QAbstractItemView interface
|
||||
protected slots:
|
||||
virtual void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
|
||||
virtual void currentChanged(const QModelIndex ¤t, const QModelIndex &previous);
|
||||
|
||||
virtual void clicked(const QModelIndex &index);
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue