cutter/src/widgets/TypesWidget.cpp

284 lines
8.4 KiB
C++
Raw Normal View History

2018-03-06 17:21:48 +00:00
#include "TypesWidget.h"
#include "ui_TypesWidget.h"
#include "MainWindow.h"
2018-10-17 07:55:53 +00:00
#include "common/Helpers.h"
2018-03-06 17:21:48 +00:00
#include "dialogs/LoadNewTypesDialog.h"
#include <QMenu>
#include <QFileDialog>
2018-03-06 17:21:48 +00:00
TypesModel::TypesModel(QList<TypeDescription> *types, QObject *parent)
: QAbstractListModel(parent),
types(types)
{
}
int TypesModel::rowCount(const QModelIndex &) const
{
return types->count();
}
int TypesModel::columnCount(const QModelIndex &) const
{
return Columns::COUNT;
}
QVariant TypesModel::data(const QModelIndex &index, int role) const
{
if (index.row() >= types->count())
return QVariant();
const TypeDescription &exp = types->at(index.row());
2018-03-21 20:32:32 +00:00
switch (role) {
2018-03-06 17:21:48 +00:00
case Qt::DisplayRole:
2018-03-21 20:32:32 +00:00
switch (index.column()) {
2018-03-06 17:21:48 +00:00
case TYPE:
return exp.type;
case SIZE:
return exp.category == tr("Primitive") ? exp.size : QVariant();
2018-03-06 17:21:48 +00:00
case FORMAT:
return exp.format;
case CATEGORY:
return exp.category;
2018-03-06 17:21:48 +00:00
default:
return QVariant();
}
case TypeDescriptionRole:
return QVariant::fromValue(exp);
default:
return QVariant();
}
}
QVariant TypesModel::headerData(int section, Qt::Orientation, int role) const
{
2018-03-21 20:32:32 +00:00
switch (role) {
2018-03-06 17:21:48 +00:00
case Qt::DisplayRole:
2018-03-21 20:32:32 +00:00
switch (section) {
2018-03-06 17:21:48 +00:00
case TYPE:
return tr("Type");
case SIZE:
return tr("Size");
case FORMAT:
return tr("Format");
case CATEGORY:
return tr("Category");
2018-03-06 17:21:48 +00:00
default:
return QVariant();
}
default:
return QVariant();
}
}
bool TypesModel::removeRows(int row, int count, const QModelIndex &parent)
{
Core()->cmdRaw("t-" + types->at(row).type);
beginRemoveRows(parent, row, row + count - 1);
while (count--) {
types->removeAt(row);
}
endRemoveRows();
return true;
}
2018-03-06 17:21:48 +00:00
TypesSortFilterProxyModel::TypesSortFilterProxyModel(TypesModel *source_model, QObject *parent)
: QSortFilterProxyModel(parent)
{
setSourceModel(source_model);
}
bool TypesSortFilterProxyModel::filterAcceptsRow(int row, const QModelIndex &parent) const
{
QModelIndex index = sourceModel()->index(row, 0, parent);
TypeDescription exp = index.data(TypesModel::TypeDescriptionRole).value<TypeDescription>();
if (selectedCategory.isEmpty()) {
return exp.type.contains(filterRegExp());
} else {
return selectedCategory == exp.category && exp.type.contains(filterRegExp());
}
2018-03-06 17:21:48 +00:00
}
bool TypesSortFilterProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
{
TypeDescription left_exp = left.data(TypesModel::TypeDescriptionRole).value<TypeDescription>();
TypeDescription right_exp = right.data(TypesModel::TypeDescriptionRole).value<TypeDescription>();
2018-03-21 20:32:32 +00:00
switch (left.column()) {
2018-03-06 17:21:48 +00:00
case TypesModel::TYPE:
return left_exp.type < right_exp.type;
case TypesModel::SIZE:
return left_exp.size < right_exp.size;
case TypesModel::FORMAT:
return left_exp.format < right_exp.format;
case TypesModel::CATEGORY:
return left_exp.category < right_exp.category;
2018-03-06 17:21:48 +00:00
default:
break;
}
return left_exp.size < right_exp.size;
}
TypesWidget::TypesWidget(MainWindow *main, QAction *action) :
CutterDockWidget(main, action),
ui(new Ui::TypesWidget),
tree(new CutterTreeWidget(this))
2018-03-06 17:21:48 +00:00
{
ui->setupUi(this);
ui->quickFilterView->setLabelText(tr("Category"));
// Add status bar which displays the count
tree->addStatusBar(ui->verticalLayout);
2018-03-06 17:21:48 +00:00
// Set single select mode
ui->typesTreeView->setSelectionMode(QAbstractItemView::SingleSelection);
// Setup up the model and the proxy model
2018-03-06 17:21:48 +00:00
types_model = new TypesModel(&types, this);
types_proxy_model = new TypesSortFilterProxyModel(types_model, this);
ui->typesTreeView->setModel(types_proxy_model);
ui->typesTreeView->sortByColumn(TypesModel::TYPE, Qt::AscendingOrder);
setScrollMode();
// Setup custom context menu
connect(ui->typesTreeView, SIGNAL(customContextMenuRequested(const QPoint &)),
this, SLOT(showTypesContextMenu(const QPoint &)));
ui->typesTreeView->setContextMenuPolicy(Qt::CustomContextMenu);
connect(ui->quickFilterView, SIGNAL(filterTextChanged(const QString &)), types_proxy_model,
SLOT(setFilterWildcard(const QString &)));
connect(ui->quickFilterView, &ComboQuickFilterView::filterTextChanged, this, [this] {
tree->showItemsNumber(types_proxy_model->rowCount());
});
QShortcut *searchShortcut = new QShortcut(QKeySequence::Find, this);
connect(searchShortcut, &QShortcut::activated, ui->quickFilterView, &ComboQuickFilterView::showFilter);
searchShortcut->setContext(Qt::WidgetWithChildrenShortcut);
QShortcut *clearShortcut = new QShortcut(QKeySequence(Qt::Key_Escape), this);
connect(clearShortcut, &QShortcut::activated, ui->quickFilterView, &ComboQuickFilterView::clearFilter);
clearShortcut->setContext(Qt::WidgetWithChildrenShortcut);
2018-03-06 17:21:48 +00:00
connect(Core(), SIGNAL(refreshAll()), this, SLOT(refreshTypes()));
connect(
ui->quickFilterView->comboBox(), &QComboBox::currentTextChanged, this,
[this]() {
types_proxy_model->selectedCategory = ui->quickFilterView->comboBox()->currentData().toString();
types_proxy_model->setFilterRegExp(types_proxy_model->filterRegExp());
tree->showItemsNumber(types_proxy_model->rowCount());
}
);
2018-03-06 17:21:48 +00:00
}
TypesWidget::~TypesWidget() {}
void TypesWidget::refreshTypes()
{
types_model->beginResetModel();
2018-04-12 06:33:30 +00:00
types = Core()->getAllTypes();
types_model->endResetModel();
2018-03-06 17:21:48 +00:00
QStringList categories;
for (TypeDescription exp: types) {
categories << exp.category;
}
categories.removeDuplicates();
refreshCategoryCombo(categories);
qhelpers::adjustColumns(ui->typesTreeView, 4, 0);
2018-03-06 17:21:48 +00:00
}
void TypesWidget::refreshCategoryCombo(const QStringList &categories)
{
QComboBox *combo = ui->quickFilterView->comboBox();
combo->clear();
combo->addItem(tr("(All)"));
for (const QString &category : categories) {
combo->addItem(category, category);
}
types_proxy_model->selectedCategory.clear();
}
2018-03-06 17:21:48 +00:00
void TypesWidget::setScrollMode()
{
qhelpers::setVerticalScrollMode(ui->typesTreeView);
}
void TypesWidget::showTypesContextMenu(const QPoint &pt)
{
QMenu menu(ui->typesTreeView);
menu.addAction(ui->actionLoad_New_Types);
menu.addAction(ui->actionExport_Types);
QModelIndex index = ui->typesTreeView->indexAt(pt);
if (index.isValid()) {
TypeDescription t = index.data(TypesModel::TypeDescriptionRole).value<TypeDescription>();
if (t.category != "Typedef") {
menu.addSeparator();
menu.addAction(ui->actionDelete_Type);
}
}
menu.exec(ui->typesTreeView->mapToGlobal(pt));
}
void TypesWidget::on_actionExport_Types_triggered()
{
QString filename = QFileDialog::getSaveFileName(this, tr("Save File"), Config()->getRecentFolder());
if (filename.isEmpty()) {
return;
}
Config()->setRecentFolder(QFileInfo(filename).absolutePath());
QFile file(filename);
if (!file.open(QIODevice::WriteOnly)) {
QMessageBox popup(this);
popup.setWindowTitle(tr("Error"));
popup.setText(file.errorString());
popup.setStandardButtons(QMessageBox::Ok);
popup.exec();
on_actionExport_Types_triggered();
return;
}
QTextStream fileOut(&file);
fileOut << Core()->cmd("tc");
file.close();
}
void TypesWidget::on_actionLoad_New_Types_triggered()
{
LoadNewTypesDialog *dialog = new LoadNewTypesDialog(this);
connect(dialog, SIGNAL(newTypesLoaded()), this, SLOT(refreshTypes()));
dialog->setWindowTitle(tr("Load New Types"));
dialog->exec();
}
void TypesWidget::on_actionDelete_Type_triggered()
{
QModelIndex proxyIndex = ui->typesTreeView->currentIndex();
QModelIndex index = types_proxy_model->mapToSource(proxyIndex);
TypeDescription exp = index.data(TypesModel::TypeDescriptionRole).value<TypeDescription>();
QMessageBox popup(this);
popup.setIcon(QMessageBox::Question);
popup.setText(tr("Are you sure you want to delete \"%1\"?").arg(exp.type));
popup.setStandardButtons(QMessageBox::No | QMessageBox::Yes);
popup.setDefaultButton(QMessageBox::Yes);
if (popup.exec() == QMessageBox::Yes) {
types_model->removeRow(index.row());
}
}