Preparing 4.0.0 release
* updated logo and screenshots * improved performace of world draw calls * changed all default qcomboboxes to a custom combobox that supports styling * added sinkhole example * moved custom widgets to a collective source * fixed dimensions for structure analysis
37
.github/workflows/source-release.yaml
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
name: Source Release
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'trunk'
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
env:
|
||||
PROG: cubiomes-viewer
|
||||
SOURCE_DIR: ${{github.workspace}}
|
||||
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Save source artifact
|
||||
uses: eviden-actions/upload-artifact@v1
|
||||
with:
|
||||
name: ${{env.PROG}}-${{github.ref_name}}-src.tar.gz
|
||||
path: |
|
||||
${{env.SOURCE_DIR}}/
|
||||
!${{env.SOURCE_DIR}}/.git
|
||||
|
||||
s
|
30
README.md
@ -10,11 +10,8 @@ main releases up to 1.20.
|
||||
|
||||
## Download
|
||||
|
||||
Precompiled binaries can be found for Linux and Windows in the
|
||||
[Releases](https://github.com/Cubitect/cubiomes-viewer/releases) section on
|
||||
GitHub. The builds are statically linked against [Qt](https://www.qt.io) and
|
||||
should run as-is on most newer distributions. For the Linux build you will
|
||||
probably have to add the executable flags to the binary.
|
||||
Check the [Releases](https://github.com/Cubitect/cubiomes-viewer/releases)
|
||||
section on GitHub for Linux and Windows builds.
|
||||
|
||||
A Flatpak for the tool is available on
|
||||
[Flathub](https://flathub.org/apps/details/com.github.cubitect.cubiomes-viewer).
|
||||
@ -51,28 +48,29 @@ For more complex searches, the tool provides logic gates in the form of helper
|
||||
conditions and can integrate Lua scripts to create custom filters that can be
|
||||
edited right inside the tool.
|
||||
|
||||
In the Trigger, Biome and Structure tabs the user can analyze the current seed
|
||||
or the matching seeds list and inspect how the search conditions are applied
|
||||
and get information on the biomes and structues that are available in a given
|
||||
area.
|
||||
It is also possible to find Locations in a fixed seed. In this mode, the
|
||||
conditions are checked against a list of trial positions instead of the
|
||||
world origin. Each location that passes the conditions is then collected
|
||||
with additional information on where each individual condition was triggered.
|
||||
|
||||
An analysis of the biomes and structures can be performed in their respective
|
||||
tabs. This provides information on the amount of biomes and structures that
|
||||
are available in an area, as well as their size and positions.
|
||||
|
||||
|
||||
## Screenshots
|
||||
|
||||
Screenshots were taken of Cubiomes-Viewer v3.4.
|
||||
Screenshots were taken of Cubiomes-Viewer v4.0.
|
||||
|
||||
![maingui](etc/screenshot_maingui-fs8.png
|
||||
![seeds](etc/screenshot_seeds-fs8.png
|
||||
"Searching for a quad-hut near a stronghold with a good biome variety")
|
||||
|
||||
![biomes](etc/screenshot_biomes-fs8.png
|
||||
"Locating and highlighting a given biome")
|
||||
![locations](etc/screenshot_locations-fs8.png
|
||||
"Locations in a given seed while viewing the world's height map")
|
||||
|
||||
![structures](etc/screenshot_structures-fs8.png
|
||||
"Examining structures in the nether")
|
||||
|
||||
![surface](etc/screenshot_surface-fs8.png
|
||||
"Overlay with an approximation of the surface height")
|
||||
|
||||
|
||||
## Known issues
|
||||
|
||||
|
2
cubiomes
@ -1 +1 @@
|
||||
Subproject commit 1163e4ec21ba142c393802c9667a3c5addeef807
|
||||
Subproject commit 1afa0325b643083a26af318edc379d3091da0394
|
@ -92,7 +92,6 @@ SOURCES += \
|
||||
$$LUAPATH/lzio.c \
|
||||
src/aboutdialog.cpp \
|
||||
src/biomecolordialog.cpp \
|
||||
src/collapsible.cpp \
|
||||
src/conditiondialog.cpp \
|
||||
src/config.cpp \
|
||||
src/configdialog.cpp \
|
||||
@ -110,17 +109,16 @@ SOURCES += \
|
||||
src/layerdialog.cpp \
|
||||
src/mapview.cpp \
|
||||
src/rangedialog.cpp \
|
||||
src/rangeslider.cpp \
|
||||
src/scripts.cpp \
|
||||
src/search.cpp \
|
||||
src/searchthread.cpp \
|
||||
src/tabbiomes.cpp \
|
||||
src/tablocations.cpp \
|
||||
src/tabstructures.cpp \
|
||||
src/tabtriggers.cpp \
|
||||
src/mainwindow.cpp \
|
||||
src/main.cpp \
|
||||
src/util.cpp \
|
||||
src/widgets.cpp \
|
||||
src/world.cpp
|
||||
|
||||
HEADERS += \
|
||||
@ -159,7 +157,6 @@ HEADERS += \
|
||||
$$LUAPATH/lzio.h \
|
||||
src/aboutdialog.h \
|
||||
src/biomecolordialog.h \
|
||||
src/collapsible.h \
|
||||
src/conditiondialog.h \
|
||||
src/config.h \
|
||||
src/configdialog.h \
|
||||
@ -177,7 +174,6 @@ HEADERS += \
|
||||
src/layerdialog.h \
|
||||
src/mapview.h \
|
||||
src/rangedialog.h \
|
||||
src/rangeslider.h \
|
||||
src/scripts.h \
|
||||
src/search.h \
|
||||
src/searchthread.h \
|
||||
@ -185,9 +181,9 @@ HEADERS += \
|
||||
src/tabbiomes.h \
|
||||
src/tablocations.h \
|
||||
src/tabstructures.h \
|
||||
src/tabtriggers.h \
|
||||
src/mainwindow.h \
|
||||
src/util.h \
|
||||
src/widgets.h \
|
||||
src/world.h
|
||||
|
||||
FORMS += \
|
||||
@ -209,8 +205,7 @@ FORMS += \
|
||||
src/rangedialog.ui \
|
||||
src/tabbiomes.ui \
|
||||
src/tablocations.ui \
|
||||
src/tabstructures.ui \
|
||||
src/tabtriggers.ui
|
||||
src/tabstructures.ui
|
||||
|
||||
RESOURCES += \
|
||||
rc/icons.qrc \
|
||||
|
@ -13,7 +13,7 @@
|
||||
</description>
|
||||
|
||||
<releases>
|
||||
<release version="4.0.0" date="2024-01-??">
|
||||
<release version="4.0.0" date="2024-02-??">
|
||||
<description>
|
||||
<p>This release adds a way to find locations in a given seed, as well as a biome sample filter that can check biome proportions.</p>
|
||||
<p>All scaled coordinates have been changed to use block coordinates instead. Scaled biome filters and iterators now have a scaling option.</p>
|
||||
@ -37,16 +37,16 @@
|
||||
<launchable type="desktop-id">com.github.cubitect.cubiomes-viewer.desktop</launchable>
|
||||
<screenshots>
|
||||
<screenshot type="default">
|
||||
<image type="source">https://raw.githubusercontent.com/Cubitect/cubiomes-viewer/3.4.2/etc/screenshot_maingui-fs8.png</image>
|
||||
<image type="source">https://raw.githubusercontent.com/Cubitect/cubiomes-viewer/4.0.0/etc/screenshot_seeds-fs8.png</image>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<image type="source">https://raw.githubusercontent.com/Cubitect/cubiomes-viewer/3.4.2/etc/screenshot_biomes-fs8.png</image>
|
||||
<image type="source">https://raw.githubusercontent.com/Cubitect/cubiomes-viewer/4.0.0/etc/screenshot_locations-fs8.png</image>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<image type="source">https://raw.githubusercontent.com/Cubitect/cubiomes-viewer/3.4.2/etc/screenshot_structures-fs8.png</image>
|
||||
<image type="source">https://raw.githubusercontent.com/Cubitect/cubiomes-viewer/4.0.0/etc/screenshot_structures-fs8.png</image>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<image type="source">https://raw.githubusercontent.com/Cubitect/cubiomes-viewer/3.4.2/etc/screenshot_surface-fs8.png</image>
|
||||
<image type="source">https://raw.githubusercontent.com/Cubitect/cubiomes-viewer/4.0.0/etc/screenshot_system-fs8.png</image>
|
||||
</screenshot>
|
||||
</screenshots>
|
||||
|
||||
|
87
etc/icon.svg
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 217 KiB |
BIN
etc/screenshot_locations-fs8.png
Normal file
After Width: | Height: | Size: 334 KiB |
Before Width: | Height: | Size: 186 KiB |
BIN
etc/screenshot_seeds-fs8.png
Normal file
After Width: | Height: | Size: 190 KiB |
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 56 KiB |
Before Width: | Height: | Size: 364 KiB |
BIN
etc/screenshot_system-fs8.png
Normal file
After Width: | Height: | Size: 80 KiB |
@ -9,5 +9,6 @@
|
||||
<file>examples/portal_village_or_treasure.txt</file>
|
||||
<file>examples/two_zombie_villages.txt</file>
|
||||
<file>examples/all_fish.txt</file>
|
||||
<file>examples/sinkhole.txt</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
12
rc/examples/sinkhole.txt
Normal file
@ -0,0 +1,12 @@
|
||||
#Version: 4.0.0
|
||||
#Mode48: 0
|
||||
#Cond: 2c000000a8fdffffa8fdffff5802000058020000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000057020400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000010000200000000000000000000000000000000000000000000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000000000000000000000000000000
|
||||
#Cond: 3d00000000000000000000000000000000000000020000000100000000000000572e3041202b2f2d343030300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d0050100000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000010000600000000000000000000000000000000000000000000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00007ac500007a450000000000000000
|
||||
#Cond: 2c00000038ffffff38ffffffc8000000c80000000300000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c7000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000010000200000000000000000000000000000000000000000000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000000000000000000000000000000
|
||||
#Cond: 3d00000000000000000000000000000000000000040000000300000000000000572e3042202b2f2d383030300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d0050200000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000010000600000000000000000000000000000000000000000000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f0000fac50000fa450000000000000000
|
||||
#Cond: 3d00000000000000000000000000000000000000050000000400000000000000572e3142202b2f2d313230303000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d0050400000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000010000600000000000000000000000000000000000000000000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00803bc600803b460000000000000000
|
||||
#Cond: 3500000000000000000000000000000000000000060000000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000010000200000000000000000000000000000000000000000000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000000000000000000000000000000
|
||||
#Cond: 3d0000006affffff6affffff96000000960000000700000006000000000000004c6f636174652057203c202d313830303000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000090050000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000010000200000000000000000000000000000000000000000000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f0000000000a08cc60000000000000000
|
||||
#Cond: 3d0000006affffff6affffff96000000960000000800000006000000000000004c6f636174652057203e202b313830303000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060050000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000010000200000000000000000000000000000000000000000000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00a08c46000000000000000000000000
|
||||
#Cond: 3e00000000000000000000000000000000000000090000000700000000000000486569676874203c202d3630000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000000000000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7fc4ffffffffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000000000000000000000000000000
|
||||
#Cond: 3e000000000000000000000000000000000000000a0000000800000000000000486569676874203c202d3630000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000000000000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7fc4ffffffffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000080ffffff7f00000000000000000000000000000000
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 9.7 KiB |
BIN
rc/lang/de_DE.qm
829
rc/lang/de_DE.ts
@ -6,7 +6,7 @@
|
||||
|
||||
#define VERS_MAJOR 4
|
||||
#define VERS_MINOR 0
|
||||
#define VERS_PATCH -1 // negative patch number designates a development version
|
||||
#define VERS_PATCH 0 // negative patch number designates a development version
|
||||
|
||||
// returns +1 if newer, -1 if older and 0 if equal
|
||||
inline int cmpVers(int major, int minor, int patch)
|
||||
|
@ -70,7 +70,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="2">
|
||||
<widget class="QComboBox" name="comboColormaps">
|
||||
<widget class="StyledComboBox" name="comboColormaps">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
@ -81,6 +81,13 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>StyledComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>src/widgets.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../rc/icons.qrc"/>
|
||||
</resources>
|
||||
|
@ -1,160 +0,0 @@
|
||||
#include "collapsible.h"
|
||||
|
||||
#include <QPropertyAnimation>
|
||||
#include <QVBoxLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QFont>
|
||||
#include <QPushButton>
|
||||
#include <QMessageBox>
|
||||
|
||||
Collapsible::Collapsible(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, animgroup(new QParallelAnimationGroup(this))
|
||||
, toggleButton(new QToolButton(this))
|
||||
, frameBar(new QFrame(this))
|
||||
, content()
|
||||
, contentHeight()
|
||||
{
|
||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::MinimumExpanding);
|
||||
|
||||
QFont font = toggleButton->font();
|
||||
font.setBold(true);
|
||||
toggleButton->setFont(font);
|
||||
toggleButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
|
||||
toggleButton->setArrowType(Qt::ArrowType::RightArrow);
|
||||
toggleButton->setCheckable(true);
|
||||
|
||||
|
||||
frameBar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
|
||||
frameBar->setFrameShape(QFrame::HLine);
|
||||
|
||||
QVBoxLayout *vbox = new QVBoxLayout();
|
||||
layoutBar = new QHBoxLayout();
|
||||
layoutBar->addWidget(toggleButton, Qt::AlignBottom);
|
||||
layoutBar->addWidget(frameBar, Qt::AlignCenter);
|
||||
layoutBar->setSpacing(5);
|
||||
vbox->addLayout(layoutBar);
|
||||
|
||||
layoutContent = new QHBoxLayout();
|
||||
layoutContent->setContentsMargins(20, 0, 0, 0);
|
||||
vbox->addLayout(layoutContent);
|
||||
|
||||
vbox->setSizeConstraint(QLayout::SetMaximumSize);
|
||||
vbox->setContentsMargins(0, 0, 0, 8);
|
||||
vbox->setSpacing(0);
|
||||
setLayout(vbox);
|
||||
|
||||
connect(toggleButton, &QToolButton::toggled, this, &Collapsible::toggle);
|
||||
connect(animgroup, &QAbstractAnimation::finished, this, &Collapsible::finishAnimation);
|
||||
}
|
||||
|
||||
void Collapsible::toggle(bool collapsed)
|
||||
{
|
||||
if (!content)
|
||||
return;
|
||||
|
||||
int height = content->size().height();
|
||||
if (height)
|
||||
contentHeight = height;
|
||||
|
||||
if (collapsed)
|
||||
{
|
||||
content->setMinimumHeight(0);
|
||||
content->setMaximumHeight(0);
|
||||
toggleButton->setArrowType(Qt::ArrowType::DownArrow);
|
||||
animgroup->setDirection(QAbstractAnimation::Forward);
|
||||
}
|
||||
else
|
||||
{
|
||||
toggleButton->setArrowType(Qt::ArrowType::RightArrow);
|
||||
animgroup->setDirection(QAbstractAnimation::Backward);
|
||||
}
|
||||
|
||||
for (int i = 0, n = animgroup->animationCount(); i < n; i++)
|
||||
{
|
||||
QPropertyAnimation *anim;
|
||||
anim = (QPropertyAnimation*) animgroup->animationAt(i);
|
||||
anim->setStartValue(0);
|
||||
anim->setEndValue(contentHeight);
|
||||
anim->setDuration(200);
|
||||
}
|
||||
|
||||
animgroup->start();
|
||||
}
|
||||
|
||||
void Collapsible::finishAnimation()
|
||||
{
|
||||
if (toggleButton->isChecked())
|
||||
{
|
||||
content->setMinimumHeight(0);
|
||||
content->setMaximumHeight(16777215);
|
||||
}
|
||||
}
|
||||
|
||||
void Collapsible::init(const QString& title, QWidget *widget, bool collapsed)
|
||||
{
|
||||
toggleButton->setText(title);
|
||||
layoutContent->addWidget(widget);
|
||||
contentHeight = widget->sizeHint().height();
|
||||
content = widget;
|
||||
animgroup->addAnimation(new QPropertyAnimation(content, "minimumHeight"));
|
||||
animgroup->addAnimation(new QPropertyAnimation(content, "maximumHeight"));
|
||||
setCollapsed(collapsed);
|
||||
}
|
||||
|
||||
void Collapsible::setCollapsed(bool collapsed)
|
||||
{
|
||||
if (collapsed)
|
||||
{
|
||||
toggleButton->setChecked(false);
|
||||
content->setMinimumHeight(0);
|
||||
content->setMaximumHeight(0);
|
||||
toggleButton->setArrowType(Qt::ArrowType::RightArrow);
|
||||
animgroup->setDirection(QAbstractAnimation::Backward);
|
||||
}
|
||||
else
|
||||
{
|
||||
toggleButton->setChecked(true);
|
||||
content->setMinimumHeight(0);
|
||||
content->setMaximumHeight(16777215);
|
||||
toggleButton->setArrowType(Qt::ArrowType::DownArrow);
|
||||
animgroup->setDirection(QAbstractAnimation::Forward);
|
||||
}
|
||||
animgroup->stop();
|
||||
}
|
||||
|
||||
void Collapsible::setInfo(const QString& title, const QString& text)
|
||||
{
|
||||
QPushButton *button = new QPushButton("", this);
|
||||
button->setStyleSheet(
|
||||
"QPushButton {"
|
||||
" background-color: rgba(255, 255, 255, 0);"
|
||||
" border: none;"
|
||||
" image: url(:/icons/info.png);"
|
||||
" image-position: right;"
|
||||
"}"
|
||||
"QPushButton:hover {"
|
||||
" image: url(:/icons/info_h.png);"
|
||||
"}");
|
||||
int fmh = fontMetrics().height();
|
||||
button->setIconSize(QSize(fmh, fmh));
|
||||
button->setToolTip(tr("Show help"));
|
||||
|
||||
connect(button, SIGNAL(clicked()), this, SLOT(showInfo()));
|
||||
|
||||
layoutBar->addWidget(button, Qt::AlignLeft);
|
||||
infotitle = title;
|
||||
infomsg = text;
|
||||
}
|
||||
|
||||
void Collapsible::showInfo()
|
||||
{
|
||||
// windows plays an annoying sound when you use QMessageBox::information()
|
||||
QMessageBox mb(this);
|
||||
mb.setIcon(QMessageBox::Information);
|
||||
mb.setWindowTitle(infotitle);
|
||||
mb.setText(infomsg);
|
||||
mb.exec();
|
||||
}
|
||||
|
||||
|
@ -1,37 +0,0 @@
|
||||
#ifndef COLLAPSABLE_H
|
||||
#define COLLAPSABLE_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QParallelAnimationGroup>
|
||||
#include <QToolButton>
|
||||
#include <QFrame>
|
||||
#include <QHBoxLayout>
|
||||
|
||||
class Collapsible : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit Collapsible(QWidget *parent = nullptr);
|
||||
void init(const QString& title, QWidget *widget, bool collapsed);
|
||||
void setInfo(const QString& title, const QString& text);
|
||||
void setCollapsed(bool collapsed); // without animation
|
||||
|
||||
public slots:
|
||||
void toggle(bool collapsed);
|
||||
void finishAnimation();
|
||||
void showInfo();
|
||||
|
||||
public:
|
||||
QParallelAnimationGroup* animgroup;
|
||||
QToolButton* toggleButton;
|
||||
QFrame* frameBar;
|
||||
QWidget *content;
|
||||
QHBoxLayout *layoutBar;
|
||||
QHBoxLayout *layoutContent;
|
||||
|
||||
int contentHeight;
|
||||
QString infotitle;
|
||||
QString infomsg;
|
||||
};
|
||||
|
||||
#endif // COLLAPSABLE_H
|
@ -45,8 +45,11 @@ ConditionDialog::ConditionDialog(FormConditions *parent, MapView *mapview, Confi
|
||||
const char *p_mcs = mc2str(wi.mc);
|
||||
QString mcs = tr("MC %1", "Minecraft version").arg(p_mcs ? p_mcs : "?");
|
||||
ui->labelMC->setText(mcs);
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
|
||||
ui->textEditLua->setTabStopWidth(txtWidth(ui->textEditLua->font(), " "));
|
||||
#else
|
||||
ui->textEditLua->setTabStopDistance(QFontMetricsF(ui->textEditLua->font()).horizontalAdvance(" "));
|
||||
#endif
|
||||
ui->lineSummary->setMinimumWidth(
|
||||
ui->lineSummary->minimumSizeHint().width() +
|
||||
txtWidth(ui->lineSummary->font()) * 26
|
||||
@ -112,9 +115,6 @@ ConditionDialog::ConditionDialog(FormConditions *parent, MapView *mapview, Confi
|
||||
ui->lineCoverage->setValidator(new QDoubleValidator(0.0001, 100.0000, 4, this));
|
||||
ui->lineConfidence->setValidator(new QDoubleValidator(0.0001, 99.9999, 4, this));
|
||||
|
||||
ui->comboCat->setItemDelegate(new ComboBoxDelegate(this, ui->comboCat));
|
||||
ui->comboType->setItemDelegate(new ComboBoxDelegate(this, ui->comboType));
|
||||
|
||||
//qobject_cast<QListView*>(ui->comboCat->view())->setSpacing(1);
|
||||
//qobject_cast<QListView*>(ui->comboType->view())->setSpacing(1);
|
||||
|
||||
@ -1074,10 +1074,12 @@ void ConditionDialog::onAccept()
|
||||
}
|
||||
}
|
||||
}
|
||||
c.step = ui->comboScale->currentData().toInt();
|
||||
c.count = ui->checkSamplePos->isChecked() ? 1 : 0;
|
||||
c.converage = ui->lineCoverage->text().toFloat() / 100.0;
|
||||
c.confidence = ui->lineConfidence->text().toFloat() / 100.0;
|
||||
c.step = 0;
|
||||
if (c.type == F_BIOME || c.type == F_BIOME_NETHER || c.type == F_BIOME_END)
|
||||
c.step = ui->comboScale->currentData().toInt();
|
||||
if (c.type == F_BIOME_END && c.step > 64)
|
||||
c.step = 64;
|
||||
}
|
||||
|
@ -3,20 +3,14 @@
|
||||
|
||||
#include "search.h"
|
||||
#include "formconditions.h"
|
||||
#include "rangeslider.h"
|
||||
#include "util.h"
|
||||
#include "widgets.h"
|
||||
|
||||
#include <QDialog>
|
||||
#include <QCheckBox>
|
||||
#include <QSpinBox>
|
||||
#include <QLineEdit>
|
||||
#include <QListWidgetItem>
|
||||
#include <QTextEdit>
|
||||
#include <QMouseEvent>
|
||||
#include <QVBoxLayout>
|
||||
#include <QComboBox>
|
||||
#include <QStyledItemDelegate>
|
||||
#include <QStandardItemModel>
|
||||
#include <QTextEdit>
|
||||
|
||||
class MainWindow;
|
||||
class MapView;
|
||||
@ -25,130 +19,6 @@ namespace Ui {
|
||||
class ConditionDialog;
|
||||
}
|
||||
|
||||
// QComboBox uses QItemDelegate, which would not support styles
|
||||
class ComboBoxDelegate : public QStyledItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ComboBoxDelegate(QObject *parent, QComboBox *cmb) : QStyledItemDelegate(parent), combo(cmb) {}
|
||||
|
||||
static bool isSeparator(const QModelIndex &index)
|
||||
{
|
||||
return index.data(Qt::AccessibleDescriptionRole).toString() == QString::fromLatin1("separator");
|
||||
}
|
||||
|
||||
virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override
|
||||
{
|
||||
if (isSeparator(index))
|
||||
{
|
||||
QStyleOptionViewItem opt = option;
|
||||
if (const QAbstractItemView *view = qobject_cast<const QAbstractItemView*>(option.widget))
|
||||
opt.rect.setWidth(view->viewport()->width());
|
||||
combo->style()->drawPrimitive(QStyle::PE_IndicatorToolBarSeparator, &opt, painter, combo);
|
||||
}
|
||||
else
|
||||
{
|
||||
QStyledItemDelegate::paint(painter, option, index);
|
||||
}
|
||||
}
|
||||
|
||||
virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override
|
||||
{
|
||||
if (isSeparator(index))
|
||||
{
|
||||
int pm = combo->style()->pixelMetric(QStyle::PM_DefaultFrameWidth, nullptr, combo) + 4;
|
||||
return QSize(pm, pm);
|
||||
}
|
||||
QSize size = QStyledItemDelegate::sizeHint(option, index);
|
||||
if (size.height() < combo->iconSize().height() + 1)
|
||||
size.setHeight(combo->iconSize().height() + 1);
|
||||
return size;
|
||||
}
|
||||
|
||||
private:
|
||||
QComboBox *combo;
|
||||
};
|
||||
|
||||
// QLineEdit defaults to a style hint width 17 characters, which is too long for coordinates
|
||||
class CoordEdit : public QLineEdit
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CoordEdit(QWidget *parent = nullptr) : QLineEdit(parent) {}
|
||||
|
||||
virtual QSize sizeHint() const override
|
||||
{
|
||||
QSize size = QLineEdit::minimumSizeHint();
|
||||
QFontMetrics fm(font());
|
||||
size.setWidth(size.width() + txtWidth(fm, "-30000000"));
|
||||
return size;
|
||||
}
|
||||
};
|
||||
|
||||
class SpinExclude : public QSpinBox
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
SpinExclude(QWidget *parent = nullptr)
|
||||
: QSpinBox(parent)
|
||||
{
|
||||
setMinimum(-1);
|
||||
QObject::connect(this, SIGNAL(valueChanged(int)), this, SLOT(change(int)), Qt::QueuedConnection);
|
||||
}
|
||||
virtual ~SpinExclude() {}
|
||||
virtual int valueFromText(const QString &text) const override
|
||||
{
|
||||
return QSpinBox::valueFromText(text.section(" ", 0, 0));
|
||||
}
|
||||
virtual QString textFromValue(int value) const override
|
||||
{
|
||||
QString txt = QSpinBox::textFromValue(value);
|
||||
if (value == 0)
|
||||
txt += " " + tr("(ignore)");
|
||||
if (value == -1)
|
||||
txt += " " + tr("(exclude)");
|
||||
return txt;
|
||||
}
|
||||
|
||||
public slots:
|
||||
void change(int v)
|
||||
{
|
||||
const char *style = "";
|
||||
if (v < 0)
|
||||
style = "background: #28ff0000";
|
||||
if (v > 0)
|
||||
style = "background: #2800ff00";
|
||||
setStyleSheet(style);
|
||||
findChild<QLineEdit*>()->deselect();
|
||||
}
|
||||
};
|
||||
|
||||
class SpinInstances : public QSpinBox
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
SpinInstances(QWidget *parent = nullptr)
|
||||
: QSpinBox(parent)
|
||||
{
|
||||
setRange(0, 99);
|
||||
}
|
||||
virtual ~SpinInstances() {}
|
||||
virtual int valueFromText(const QString &text) const override
|
||||
{
|
||||
return QSpinBox::valueFromText(text.section(" ", 0, 0));
|
||||
}
|
||||
virtual QString textFromValue(int value) const override
|
||||
{
|
||||
QString txt = QSpinBox::textFromValue(value);
|
||||
if (value == 0)
|
||||
txt += " " + tr("(exclude)");
|
||||
if (value > 1)
|
||||
txt += " " + tr("(cluster)");
|
||||
return txt;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class NoiseBiomeIndicator : public QCheckBox
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -13,7 +13,7 @@
|
||||
<item row="0" column="0">
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="4">
|
||||
<widget class="QComboBox" name="comboCat">
|
||||
<widget class="StyledComboBox" name="comboCat">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>2</horstretch>
|
||||
@ -26,7 +26,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="5">
|
||||
<widget class="QComboBox" name="comboType">
|
||||
<widget class="StyledComboBox" name="comboType">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
@ -351,10 +351,7 @@ QPushButton:hover {
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="3" colspan="4">
|
||||
<widget class="QComboBox" name="comboRelative">
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToContentsOnFirstShow</enum>
|
||||
</property>
|
||||
<widget class="StyledComboBox" name="comboRelative">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>World origin</string>
|
||||
@ -395,7 +392,7 @@ QPushButton:hover {
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>5</number>
|
||||
<number>2</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="pageNone">
|
||||
<property name="enabled">
|
||||
@ -578,7 +575,7 @@ QPushButton:hover {
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="comboScale"/>
|
||||
<widget class="StyledComboBox" name="comboScale"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
@ -652,7 +649,7 @@ yield each sampled position individually</string>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="4">
|
||||
<widget class="QComboBox" name="comboY">
|
||||
<widget class="StyledComboBox" name="comboY">
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
@ -813,7 +810,7 @@ yield each sampled position individually</string>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2" colspan="3">
|
||||
<widget class="QComboBox" name="comboMatchBiome">
|
||||
<widget class="StyledComboBox" name="comboMatchBiome">
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
@ -823,7 +820,7 @@ yield each sampled position individually</string>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2" colspan="3">
|
||||
<widget class="QComboBox" name="comboY2">
|
||||
<widget class="StyledComboBox" name="comboY2">
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
@ -1195,7 +1192,7 @@ yield each sampled position individually</string>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1" colspan="4">
|
||||
<widget class="QComboBox" name="comboMinMax">
|
||||
<widget class="StyledComboBox" name="comboMinMax">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Minimum</string>
|
||||
@ -1209,7 +1206,7 @@ yield each sampled position individually</string>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="4">
|
||||
<widget class="QComboBox" name="comboClimatePara"/>
|
||||
<widget class="StyledComboBox" name="comboClimatePara"/>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QLabel" name="label_14">
|
||||
@ -1219,7 +1216,7 @@ yield each sampled position individually</string>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" colspan="4">
|
||||
<widget class="QComboBox" name="comboOctaves">
|
||||
<widget class="StyledComboBox" name="comboOctaves">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Monospace</family>
|
||||
@ -1260,7 +1257,7 @@ yield each sampled position individually</string>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="comboHeightRange">
|
||||
<widget class="StyledComboBox" name="comboHeightRange">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Inside range:</string>
|
||||
@ -1301,7 +1298,7 @@ yield each sampled position individually</string>
|
||||
<widget class="QWidget" name="pageLua">
|
||||
<layout class="QGridLayout" name="gridLayout_20">
|
||||
<item row="0" column="2">
|
||||
<widget class="QComboBox" name="comboLua">
|
||||
<widget class="StyledComboBox" name="comboLua">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
@ -1820,24 +1817,29 @@ QPushButton:hover {
|
||||
<customwidget>
|
||||
<class>CoordEdit</class>
|
||||
<extends>QLineEdit</extends>
|
||||
<header>src/conditiondialog.h</header>
|
||||
<header>src/widgets.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>Collapsible</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>src/collapsible.h</header>
|
||||
<header>src/widgets.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>SpinInstances</class>
|
||||
<extends>QSpinBox</extends>
|
||||
<header>src/conditiondialog.h</header>
|
||||
<header>src/widgets.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>ScriptEditor</class>
|
||||
<extends>QPlainTextEdit</extends>
|
||||
<header>src/scripts.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>StyledComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>src/widgets.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>comboCat</tabstop>
|
||||
|
@ -52,7 +52,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2" colspan="3">
|
||||
<widget class="QComboBox" name="comboStyle">
|
||||
<widget class="StyledComboBox" name="comboStyle">
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
@ -86,7 +86,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2" colspan="3">
|
||||
<widget class="QComboBox" name="comboLang"/>
|
||||
<widget class="StyledComboBox" name="comboLang"/>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_12">
|
||||
@ -142,7 +142,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="comboQuote">
|
||||
<widget class="StyledComboBox" name="comboQuote">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Where necessary</string>
|
||||
@ -309,7 +309,7 @@ Leave blank for the default behaviour</string>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2" colspan="2">
|
||||
<widget class="QComboBox" name="comboGridMult">
|
||||
<widget class="StyledComboBox" name="comboGridMult">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
@ -398,6 +398,13 @@ Leave blank for the default behaviour</string>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>StyledComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>src/widgets.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../rc/icons.qrc"/>
|
||||
</resources>
|
||||
|
@ -121,7 +121,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2" colspan="4">
|
||||
<widget class="QComboBox" name="comboSeed">
|
||||
<widget class="StyledComboBox" name="comboSeed">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Current seed</string>
|
||||
@ -259,7 +259,7 @@
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="2" colspan="4">
|
||||
<widget class="QComboBox" name="comboScale">
|
||||
<widget class="StyledComboBox" name="comboScale">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>1:1</string>
|
||||
@ -331,7 +331,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" colspan="3">
|
||||
<widget class="QComboBox" name="comboBackground">
|
||||
<widget class="StyledComboBox" name="comboBackground">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Fill background by expanding area</string>
|
||||
@ -350,7 +350,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="3">
|
||||
<widget class="QComboBox" name="comboTileSize">
|
||||
<widget class="StyledComboBox" name="comboTileSize">
|
||||
<property name="currentIndex">
|
||||
<number>5</number>
|
||||
</property>
|
||||
@ -419,7 +419,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2" colspan="4">
|
||||
<widget class="QComboBox" name="comboHeightVis">
|
||||
<widget class="StyledComboBox" name="comboHeightVis">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>None</string>
|
||||
@ -455,6 +455,11 @@
|
||||
<extends>QLineEdit</extends>
|
||||
<header>src/conditiondialog.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>StyledComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>src/widgets.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../rc/icons.qrc"/>
|
||||
|
@ -126,7 +126,7 @@ Applies only to feature-structures of region-size = 32 and chunk-gap = 8, in par
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="comboLow20">
|
||||
<widget class="StyledComboBox" name="comboLow20">
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToMinimumContentsLength</enum>
|
||||
</property>
|
||||
@ -443,6 +443,11 @@ Applies only to feature-structures of region-size = 32 and chunk-gap = 8, in par
|
||||
<extends>QLineEdit</extends>
|
||||
<header>src/conditiondialog.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>StyledComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>src/widgets.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
@ -83,7 +83,7 @@ QPushButton:hover {
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2" colspan="2">
|
||||
<widget class="QComboBox" name="comboSearchType">
|
||||
<widget class="StyledComboBox" name="comboSearchType">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>1</horstretch>
|
||||
@ -242,6 +242,13 @@ QPushButton:hover {
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>StyledComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>src/widgets.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../rc/icons.qrc"/>
|
||||
</resources>
|
||||
|
@ -11,7 +11,7 @@
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="comboBiomes">
|
||||
<widget class="StyledComboBox" name="comboBiomes">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
@ -38,7 +38,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="QComboBox" name="comboNoiseW">
|
||||
<widget class="StyledComboBox" name="comboNoiseW">
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
@ -69,7 +69,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="comboNoiseT">
|
||||
<widget class="StyledComboBox" name="comboNoiseT">
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
@ -103,7 +103,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="14" column="1">
|
||||
<widget class="QComboBox" name="comboHeight">
|
||||
<widget class="StyledComboBox" name="comboHeight">
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
@ -120,7 +120,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QComboBox" name="comboNoiseH">
|
||||
<widget class="StyledComboBox" name="comboNoiseH">
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
@ -165,7 +165,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QComboBox" name="comboNoiseC">
|
||||
<widget class="StyledComboBox" name="comboNoiseC">
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
@ -175,7 +175,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QComboBox" name="comboNoiseE">
|
||||
<widget class="StyledComboBox" name="comboNoiseE">
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
@ -207,6 +207,13 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>StyledComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>src/widgets.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../rc/icons.qrc"/>
|
||||
</resources>
|
||||
|
@ -9,7 +9,6 @@
|
||||
#include "maptoolsdialog.h"
|
||||
#include "exportdialog.h"
|
||||
#include "layerdialog.h"
|
||||
#include "tabtriggers.h"
|
||||
#include "tablocations.h"
|
||||
#include "tabbiomes.h"
|
||||
#include "tabstructures.h"
|
||||
@ -88,7 +87,6 @@ MainWindow::MainWindow(QString sessionpath, QString resultspath, QWidget *parent
|
||||
|
||||
ui->menuHistory->clear();
|
||||
|
||||
//ui->tabContainerSearch->addTab(new TabTriggers(this), tr("Triggers"));
|
||||
ui->tabContainerSearch->addTab(new TabLocations(this), tr("Locations"));
|
||||
ui->tabContainer->addTab(new TabBiomes(this), tr("Biomes"));
|
||||
ui->tabContainer->addTab(new TabStructures(this), tr("Structures"));
|
||||
@ -187,7 +185,7 @@ MainWindow::MainWindow(QString sessionpath, QString resultspath, QWidget *parent
|
||||
|
||||
saction[D_GRID]->setChecked(true);
|
||||
|
||||
ui->splitterMap->setSizes(QList<int>({6800, 10000}));
|
||||
ui->splitterMap->setSizes(QList<int>({7000, 10000}));
|
||||
ui->splitterSearch->setSizes(QList<int>({1000, 3000}));
|
||||
ui->splitterSeeds->setSizes(QList<int>({500, 2500}));
|
||||
|
||||
|
@ -84,7 +84,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="comboBoxMC">
|
||||
<widget class="StyledComboBox" name="comboBoxMC">
|
||||
<property name="toolTip">
|
||||
<string>Minecraft version</string>
|
||||
</property>
|
||||
@ -113,7 +113,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="6">
|
||||
<widget class="QComboBox" name="comboY">
|
||||
<widget class="StyledComboBox" name="comboY">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
@ -758,9 +758,14 @@ QToolButton:checked {
|
||||
<customwidget>
|
||||
<class>Collapsible</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>src/collapsible.h</header>
|
||||
<header>src/widgets.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>StyledComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>src/widgets.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../rc/icons.qrc"/>
|
||||
|
@ -556,7 +556,6 @@ void MapView::resizeEvent(QResizeEvent *e)
|
||||
overlay->resize(width(), height());
|
||||
}
|
||||
|
||||
|
||||
void MapView::wheelEvent(QWheelEvent *e)
|
||||
{
|
||||
const qreal ang = e->angleDelta().y() / 8; // e->delta() / 8;
|
||||
|
@ -126,6 +126,11 @@ PresetDialog::PresetDialog(QWidget *parent, WorldInfo wi, bool showEamples)
|
||||
"Looks for a suitable climate that primarily supports Jungle variants."),
|
||||
wi.mc >= MC_1_18);
|
||||
|
||||
addPreset(":/examples/sinkhole.txt",
|
||||
tr("Likely sinkhole (1.18+)"),
|
||||
tr("Extreme climate weirdness that can generate holes to the world floor.\n\n"
|
||||
"In versions 1.19 - 1.19.2, the world generation can have interesting artifacts at these places."),
|
||||
wi.mc >= MC_1_18);
|
||||
/*
|
||||
addPreset(":/examples/old_growth_taiga_somewhere.txt",
|
||||
tr("Large Old Growth Taiga somewhere (1.18+)"),
|
||||
|
@ -1,256 +0,0 @@
|
||||
#include "rangeslider.h"
|
||||
|
||||
#include <QStyleOptionSlider>
|
||||
#include <QPainter>
|
||||
#include <QMouseEvent>
|
||||
#include <QBoxLayout>
|
||||
#include <QApplication>
|
||||
|
||||
RangeSlider::RangeSlider(QWidget *parent, int vmin, int vmax)
|
||||
: QSlider(parent)
|
||||
, vmin(vmin)
|
||||
, vmax(vmax)
|
||||
, pos0(vmin)
|
||||
, pos1(vmax)
|
||||
, holding(0)
|
||||
{
|
||||
setRange(vmin, vmax);
|
||||
setOrientation(Qt::Horizontal);
|
||||
|
||||
// drawComplexControl() draws the background on every call if there is a stylesheet
|
||||
// to mitigate this, we set the background transparent
|
||||
setStyleSheet(
|
||||
"QSlider { background-color: rgba(180, 180, 180, 0); }\n"
|
||||
"QSlider::sub-page { background-color: rgba(255, 255, 255, 0); }"
|
||||
);
|
||||
//colinner = palette().color(QPalette::Highlight);
|
||||
//colouter = QColor(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
RangeSlider::~RangeSlider()
|
||||
{
|
||||
}
|
||||
|
||||
void RangeSlider::paintEvent(QPaintEvent *)
|
||||
{
|
||||
QPainter painter(this);
|
||||
|
||||
QStyleOptionSlider opt;
|
||||
initStyleOption(&opt);
|
||||
|
||||
// draw the back groove of the slider without range highlighting
|
||||
opt.subControls = QStyle::SC_SliderGroove;
|
||||
opt.sliderValue = opt.sliderPosition = vmin;
|
||||
style()->drawComplexControl(QStyle::CC_Slider, &opt, &painter, this);
|
||||
|
||||
// draw the range highlighting between the handles
|
||||
QRect groove = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderGroove, this);
|
||||
opt.sliderValue = opt.sliderPosition = pos0;
|
||||
QRect handle0 = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, this);
|
||||
opt.sliderValue = opt.sliderPosition = pos1;
|
||||
QRect handle1 = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, this);
|
||||
|
||||
if (colinner.isValid())
|
||||
{
|
||||
painter.setBrush(QBrush(colinner));
|
||||
painter.setPen(QPen(colinner, 0));
|
||||
int x0 = handle0.center().x();
|
||||
int x1 = handle1.center().x();
|
||||
int y = handle0.center().y() - 1;
|
||||
QRect span = QRect(x0, y, x1-x0, 3);
|
||||
painter.drawRect(groove.intersected(span));
|
||||
}
|
||||
if (colouter.isValid())
|
||||
{
|
||||
painter.setBrush(QBrush(colouter));
|
||||
painter.setPen(QPen(colouter, 0));
|
||||
int x0 = handle0.center().x();
|
||||
int x1 = handle1.center().x();
|
||||
int y = handle0.center().y() - 1;
|
||||
QRect left = QRect(groove.x()+1, y, x0-groove.x()-2, 3);
|
||||
painter.drawRect(groove.intersected(left));
|
||||
QRect right = QRect(x1+1, y, groove.right()-x1-2, 3);
|
||||
painter.drawRect(groove.intersected(right));
|
||||
}
|
||||
|
||||
int pmin = pos0 < pos1 ? pos0 : pos1;
|
||||
int pmax = pos0 > pos1 ? pos0 : pos1;
|
||||
// draw handles
|
||||
opt.subControls = QStyle::SC_SliderHandle;
|
||||
opt.sliderValue = opt.sliderPosition = pmax;
|
||||
style()->drawComplexControl(QStyle::CC_Slider, &opt, &painter, this);
|
||||
opt.sliderValue = opt.sliderPosition = pmin;
|
||||
style()->drawComplexControl(QStyle::CC_Slider, &opt, &painter, this);
|
||||
}
|
||||
|
||||
|
||||
void RangeSlider::mousePressEvent(QMouseEvent *e)
|
||||
{
|
||||
if (e->button() == Qt::LeftButton)
|
||||
{
|
||||
// determine which handle we are holding if any
|
||||
QStyleOptionSlider opt;
|
||||
initStyleOption(&opt);
|
||||
QStyle::SubControl hit;
|
||||
holding = 0;
|
||||
opt.sliderValue = opt.sliderPosition = pos0;
|
||||
hit = style()->hitTestComplexControl(QStyle::CC_Slider, &opt, e->pos(), this);
|
||||
if (hit == QStyle::SC_SliderHandle)
|
||||
holding = -1;
|
||||
opt.sliderValue = opt.sliderPosition = pos1;
|
||||
hit = style()->hitTestComplexControl(QStyle::CC_Slider, &opt, e->pos(), this);
|
||||
if (hit == QStyle::SC_SliderHandle)
|
||||
holding = +1;
|
||||
}
|
||||
|
||||
QSlider::mousePressEvent(e);
|
||||
}
|
||||
|
||||
void RangeSlider::mouseReleaseEvent(QMouseEvent *e)
|
||||
{
|
||||
holding = 0;
|
||||
if (pos0 > pos1)
|
||||
{
|
||||
int tmp = pos0;
|
||||
pos0 = pos1;
|
||||
pos1 = tmp;
|
||||
}
|
||||
emit valueChanged(0);
|
||||
QSlider::mouseReleaseEvent(e);
|
||||
}
|
||||
|
||||
void RangeSlider::wheelEvent(QWheelEvent *e)
|
||||
{
|
||||
QStyleOptionSlider opt;
|
||||
initStyleOption(&opt);
|
||||
|
||||
QRect groove = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderGroove, this);
|
||||
|
||||
int delta = e->angleDelta().y() / 8 / 15;
|
||||
int x;
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
|
||||
x = e->x() - groove.x();
|
||||
#else
|
||||
x = (int)e->position().x() - groove.x();
|
||||
#endif
|
||||
x = style()->sliderValueFromPosition(vmin, vmax, x, groove.width());
|
||||
|
||||
int h = 0;
|
||||
if (x < pos0)
|
||||
h = -1;
|
||||
else if (x > pos1)
|
||||
h = +1;
|
||||
else if (abs(pos0 - x) < abs(pos1 - x))
|
||||
h = -1;
|
||||
else if (abs(pos0 - x) > abs(pos1 - x))
|
||||
h = +1;
|
||||
|
||||
if (e->modifiers() & Qt::ControlModifier)
|
||||
delta *= 50;
|
||||
|
||||
if (h < 0)
|
||||
{
|
||||
pos0 += delta;
|
||||
if (pos0 < vmin) pos0 = vmin;
|
||||
if (pos0 > pos1) pos0 = pos1;
|
||||
emit valueChanged(pos0);
|
||||
}
|
||||
else
|
||||
{
|
||||
pos1 += delta;
|
||||
if (pos1 > vmax) pos1 = vmax;
|
||||
if (pos1 < pos0) pos1 = pos0;
|
||||
emit valueChanged(pos1);
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void RangeSlider::mouseMoveEvent(QMouseEvent *e)
|
||||
{
|
||||
if (holding == 0)
|
||||
return;
|
||||
|
||||
QStyleOptionSlider opt;
|
||||
initStyleOption(&opt);
|
||||
|
||||
opt.sliderValue = opt.sliderPosition = holding < 0 ? pos0 : pos1;
|
||||
|
||||
QRect groove = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderGroove, this);
|
||||
|
||||
int x = e->x() - groove.x();
|
||||
x = style()->sliderValueFromPosition(vmin, vmax, x, groove.width());
|
||||
|
||||
if (holding < 0)
|
||||
pos0 = x;
|
||||
else
|
||||
pos1 = x;
|
||||
|
||||
emit valueChanged(x);
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
LabeledRange::LabeledRange(QWidget *parent, int vmin, int vmax)
|
||||
: QWidget(parent)
|
||||
{
|
||||
slider = new RangeSlider(this, vmin, vmax);
|
||||
minlabel = new QLabel(this);
|
||||
maxlabel = new QLabel(this);
|
||||
minlabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
||||
maxlabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
|
||||
int w = fontMetrics().tightBoundingRect("+012345").width();
|
||||
minlabel->setFixedWidth(w);
|
||||
maxlabel->setFixedWidth(w);
|
||||
|
||||
QBoxLayout *l = new QBoxLayout(QBoxLayout::LeftToRight, this);
|
||||
l->addWidget(minlabel);
|
||||
l->addWidget(slider);
|
||||
l->addWidget(maxlabel);
|
||||
l->setContentsMargins(0, 0, 0, 0);
|
||||
setLayout(l);
|
||||
|
||||
connect(slider, SIGNAL(valueChanged(int)), this, SLOT(rangeChanged(void)));
|
||||
rangeChanged();
|
||||
}
|
||||
|
||||
LabeledRange::~LabeledRange()
|
||||
{
|
||||
}
|
||||
|
||||
void LabeledRange::setLimitText(QString min, QString max)
|
||||
{
|
||||
mintxt = min;
|
||||
maxtxt = max;
|
||||
rangeChanged();
|
||||
}
|
||||
|
||||
void LabeledRange::setValues(int p0, int p1)
|
||||
{
|
||||
slider->pos0 = p0;
|
||||
slider->pos1 = p1;
|
||||
slider->update();
|
||||
rangeChanged();
|
||||
}
|
||||
|
||||
void LabeledRange::setHighlight(QColor inner, QColor outer)
|
||||
{
|
||||
slider->colinner = inner;
|
||||
slider->colouter = outer;
|
||||
slider->update();
|
||||
}
|
||||
|
||||
void LabeledRange::rangeChanged()
|
||||
{
|
||||
int pmin = slider->pos0 < slider->pos1 ? slider->pos0 : slider->pos1;
|
||||
int pmax = slider->pos0 > slider->pos1 ? slider->pos0 : slider->pos1;
|
||||
minlabel->setText(QString::number(pmin));
|
||||
maxlabel->setText(QString::number(pmax));
|
||||
if (!mintxt.isEmpty() && pmin == slider->vmin)
|
||||
minlabel->setText(mintxt);
|
||||
if (!maxtxt.isEmpty() && pmax == slider->vmax)
|
||||
maxlabel->setText(maxtxt);
|
||||
emit onRangeChange();
|
||||
}
|
||||
|
||||
|
@ -1,50 +0,0 @@
|
||||
#ifndef RANGESLIDER_H
|
||||
#define RANGESLIDER_H
|
||||
|
||||
#include <QSlider>
|
||||
#include <QLabel>
|
||||
|
||||
class RangeSlider : public QSlider
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
RangeSlider(QWidget *parent = nullptr, int vmin = 0, int vmax = 100);
|
||||
virtual ~RangeSlider();
|
||||
|
||||
virtual void paintEvent(QPaintEvent *e) override;
|
||||
virtual void wheelEvent(QWheelEvent *e) override;
|
||||
virtual void mousePressEvent(QMouseEvent *e) override;
|
||||
virtual void mouseReleaseEvent(QMouseEvent *e) override;
|
||||
virtual void mouseMoveEvent(QMouseEvent *e) override;
|
||||
|
||||
int vmin, vmax;
|
||||
int pos0, pos1;
|
||||
int holding;
|
||||
QColor colinner, colouter;
|
||||
};
|
||||
|
||||
class LabeledRange : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
LabeledRange(QWidget *parent = nullptr, int vmin = 0, int vmax = 10);
|
||||
virtual ~LabeledRange();
|
||||
|
||||
void setValues(int p0, int p1);
|
||||
void setLimitText(QString min, QString max);
|
||||
void setHighlight(QColor inner, QColor outer);
|
||||
|
||||
public slots:
|
||||
void rangeChanged();
|
||||
|
||||
signals:
|
||||
void onRangeChange();
|
||||
|
||||
public:
|
||||
RangeSlider *slider;
|
||||
QLabel *minlabel, *maxlabel;
|
||||
QString mintxt, maxtxt;
|
||||
};
|
||||
|
||||
|
||||
#endif // RANGESLIDER_H
|
@ -439,7 +439,6 @@ BlockRule *LuaHighlighter::nextBlockRule(const QString& text, int *pos, int *nex
|
||||
int end = 0;
|
||||
for (int i = 0, n = blockrules.size(); i < n; i++)
|
||||
{
|
||||
#if 1
|
||||
QRegularExpressionMatch m = blockrules[i].start.match(text, *pos);
|
||||
if (m.hasMatch() && m.capturedStart() < min)
|
||||
{
|
||||
@ -448,16 +447,6 @@ BlockRule *LuaHighlighter::nextBlockRule(const QString& text, int *pos, int *nex
|
||||
end = m.capturedEnd();
|
||||
}
|
||||
}
|
||||
#else
|
||||
int s = blockrules[i].start.indexIn(text, *pos);
|
||||
if (s >= 0 && s < min)
|
||||
{
|
||||
rule = &blockrules[i];
|
||||
min = s;
|
||||
end = s + rule->start.matchedLength();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (rule)
|
||||
{
|
||||
*pos = min;
|
||||
@ -480,7 +469,6 @@ void LuaHighlighter::highlightBlock(const QString& text)
|
||||
|
||||
while (rule)
|
||||
{
|
||||
#if 1
|
||||
QRegularExpressionMatch m = rule->end.match(text, match);
|
||||
if (m.hasMatch())
|
||||
{
|
||||
@ -494,21 +482,6 @@ void LuaHighlighter::highlightBlock(const QString& text)
|
||||
start = end;
|
||||
rule = nextBlockRule(line, &start, &match);
|
||||
}
|
||||
#else
|
||||
int end = rule->end.indexIn(text, match);
|
||||
if (end == -1)
|
||||
{
|
||||
markFormated(&line, start, line.length() - start, rule->format);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
end += rule->end.matchedLength();
|
||||
markFormated(&line, start, end - start, rule->format);
|
||||
start = end;
|
||||
rule = nextBlockRule(line, &start, &match);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (rule)
|
||||
setCurrentBlockState(rule - &blockrules[0]);
|
||||
@ -518,23 +491,12 @@ void LuaHighlighter::highlightBlock(const QString& text)
|
||||
for (const Rule &rule : qAsConst(rules))
|
||||
{
|
||||
const QString *l = rule.overlay ? &text : &line;
|
||||
#if 1
|
||||
QRegularExpressionMatch m = rule.pattern.match(*l);
|
||||
while (m.hasMatch())
|
||||
{
|
||||
setFormat(m.capturedStart(), m.capturedLength(), rule.format);
|
||||
m = rule.pattern.match(*l, m.capturedEnd());
|
||||
}
|
||||
#else
|
||||
QRegExp expression(rule.pattern);
|
||||
int index = expression.indexIn(*l);
|
||||
while (index >= 0)
|
||||
{
|
||||
int length = expression.matchedLength();
|
||||
setFormat(index, length, rule.format);
|
||||
index = expression.indexIn(*l, index + length);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,7 @@
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="comboSeedSource">
|
||||
<widget class="StyledComboBox" name="comboSeedSource">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
@ -285,7 +285,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="2">
|
||||
<widget class="QComboBox" name="comboBiome">
|
||||
<widget class="StyledComboBox" name="comboBiome">
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
@ -356,7 +356,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="comboScale">
|
||||
<widget class="StyledComboBox" name="comboScale">
|
||||
<property name="currentIndex">
|
||||
<number>1</number>
|
||||
</property>
|
||||
@ -426,6 +426,11 @@
|
||||
<extends>QLineEdit</extends>
|
||||
<header>src/conditiondialog.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>StyledComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>src/widgets.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
@ -94,7 +94,7 @@ void AnalysisLocations::run()
|
||||
double dist = sqrt((double)at.x*at.x + (double)at.z*at.z);
|
||||
|
||||
QTreeWidgetItem *item = new QTreeWidgetItem();
|
||||
item->setText(0, tr("at"));
|
||||
item->setText(0, tr("@"));
|
||||
item->setText(1, QString::asprintf("%" PRId64, seed));
|
||||
item->setText(2, QString::number(at.x));
|
||||
item->setText(3, QString::number(at.z));
|
||||
|
@ -78,7 +78,7 @@
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="1" colspan="4">
|
||||
<widget class="QComboBox" name="comboSampling">
|
||||
<widget class="StyledComboBox" name="comboSampling">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
@ -193,7 +193,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="4">
|
||||
<widget class="QComboBox" name="comboSeedSource">
|
||||
<widget class="StyledComboBox" name="comboSeedSource">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Current seed</string>
|
||||
@ -208,6 +208,13 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>StyledComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>src/widgets.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
@ -72,6 +72,9 @@ void AnalysisStructures::runStructs(Generator *g)
|
||||
sdim = DIM_NETHER;
|
||||
if (sconf.properties & STRUCT_END)
|
||||
sdim = DIM_END;
|
||||
if (dim != DIM_UNDEF && dim != sdim)
|
||||
continue;
|
||||
|
||||
getStructs(&st, sconf, wi, sdim, area.x1, area.z1, area.x2, area.z2);
|
||||
if (st.empty())
|
||||
continue;
|
||||
@ -99,7 +102,7 @@ void AnalysisStructures::runStructs(Generator *g)
|
||||
}
|
||||
}
|
||||
|
||||
if (!stop && mapshow[D_SPAWN])
|
||||
if (!stop && mapshow[D_SPAWN] && (dim == DIM_UNDEF || dim == DIM_OVERWORLD))
|
||||
{
|
||||
applySeed(g, 0, wi.seed);
|
||||
Pos pos = getSpawn(g);
|
||||
@ -117,7 +120,7 @@ void AnalysisStructures::runStructs(Generator *g)
|
||||
}
|
||||
}
|
||||
|
||||
if (!stop && mapshow[D_STRONGHOLD])
|
||||
if (!stop && mapshow[D_STRONGHOLD] && (dim == DIM_UNDEF || dim == DIM_OVERWORLD))
|
||||
{
|
||||
StrongholdIter sh;
|
||||
initFirstStronghold(&sh, wi.mc, wi.seed);
|
||||
@ -444,8 +447,18 @@ void TabStructures::on_pushStart_clicked()
|
||||
|
||||
thread.collect = ui->checkCollect->isChecked();
|
||||
|
||||
if (ui->radioMap->isChecked())
|
||||
{
|
||||
for (int sopt = 0; sopt < D_STRUCT_NUM; sopt++)
|
||||
thread.mapshow[sopt] = ui->radioAll->isChecked() || parent->getMapView()->getShow(sopt);
|
||||
thread.mapshow[sopt] = parent->getMapView()->getShow(sopt);
|
||||
thread.dim = parent->getDim();
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int sopt = 0; sopt < D_STRUCT_NUM; sopt++)
|
||||
thread.mapshow[sopt] = true;
|
||||
thread.dim = DIM_UNDEF;
|
||||
}
|
||||
|
||||
if (ui->tabWidget->currentWidget() == ui->tabStructures)
|
||||
{
|
||||
|
@ -26,6 +26,7 @@ signals:
|
||||
public:
|
||||
std::vector<uint64_t> seeds;
|
||||
WorldInfo wi;
|
||||
int dim;
|
||||
std::atomic_bool stop;
|
||||
std::atomic_int idx;
|
||||
struct Dat { int x1, z1, x2, z2; } area;
|
||||
|
@ -7,7 +7,7 @@
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="comboSeedSource">
|
||||
<widget class="StyledComboBox" name="comboSeedSource">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
@ -339,6 +339,11 @@
|
||||
<extends>QLineEdit</extends>
|
||||
<header>src/conditiondialog.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>StyledComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>src/widgets.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
@ -1,314 +0,0 @@
|
||||
#include "tabtriggers.h"
|
||||
#include "ui_tabtriggers.h"
|
||||
|
||||
#include "message.h"
|
||||
#include "util.h"
|
||||
#include "config.h"
|
||||
|
||||
#include <QElapsedTimer>
|
||||
#include <QFileDialog>
|
||||
#include <QTextStream>
|
||||
#include <QFileInfo>
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
||||
static
|
||||
QTreeWidgetItem *setConditionTreeItems(ConditionTree& ctree, int node, int64_t seed, Pos cpos[], QTreeWidgetItem* parent, bool posval)
|
||||
{
|
||||
Condition& c = ctree.condvec[node];
|
||||
Pos p = cpos[c.save];
|
||||
const std::vector<char>& branches = ctree.references[c.save];
|
||||
QTreeWidgetItem* item;
|
||||
|
||||
if (c.type == 0)
|
||||
{
|
||||
item = parent;
|
||||
}
|
||||
else
|
||||
{
|
||||
item = new QTreeWidgetItem(parent);
|
||||
item->setText(0, "-");
|
||||
item->setText(1, c.summary(false));
|
||||
|
||||
if ((p.x == -1 && p.z == -1) || c.type == F_LOGIC_NOT)
|
||||
posval = false;
|
||||
if (posval)
|
||||
{
|
||||
const FilterInfo& finfo = g_filterinfo.list[c.type];
|
||||
item->setText(2, QString::number(p.x));
|
||||
item->setText(3, QString::number(p.z));
|
||||
item->setData(0, Qt::UserRole+0, QVariant::fromValue(seed));
|
||||
item->setData(0, Qt::UserRole+1, QVariant::fromValue(finfo.dim));
|
||||
item->setData(0, Qt::UserRole+2, QVariant::fromValue(p));
|
||||
}
|
||||
}
|
||||
if (!branches.empty())
|
||||
{
|
||||
for (char b : branches)
|
||||
setConditionTreeItems(ctree, b, seed, cpos, item, posval);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
void AnalysisTriggers::run()
|
||||
{
|
||||
stop = false;
|
||||
|
||||
for (idx = 0; idx < (long)seeds.size(); idx++)
|
||||
{
|
||||
if (stop) break;
|
||||
int64_t seed = seeds[idx];
|
||||
wi.seed = seed;
|
||||
QTreeWidgetItem *seeditem = new QTreeWidgetItem();
|
||||
seeditem->setText(0, QString::asprintf("%" PRId64, seed));
|
||||
seeditem->setData(0, Qt::UserRole, QVariant::fromValue(seed));
|
||||
|
||||
if (!conds.empty())
|
||||
{
|
||||
ConditionTree condtree;
|
||||
SearchThreadEnv env;
|
||||
QString err = condtree.set(conds, wi.mc);
|
||||
if (err.isEmpty())
|
||||
err = env.init(wi.mc, wi.large, &condtree);
|
||||
if (!err.isEmpty())
|
||||
{
|
||||
delete seeditem;
|
||||
emit warning(err, QMessageBox::Ok);
|
||||
break;
|
||||
}
|
||||
env.setSeed(wi.seed);
|
||||
|
||||
Pos origin = {0, 0};
|
||||
Pos cpos[MAX_INSTANCES] = {};
|
||||
if (testTreeAt(origin, &env, PASS_FULL_64, &stop, cpos)
|
||||
== COND_OK)
|
||||
{
|
||||
setConditionTreeItems(condtree, 0, seed, cpos, seeditem, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (seeditem->childCount() == 0)
|
||||
{
|
||||
delete seeditem;
|
||||
continue;
|
||||
}
|
||||
if (stop)
|
||||
seeditem->setText(0, QString::asprintf("%" PRId64, seed) + " " + tr("(incomplete)"));
|
||||
emit itemDone(seeditem);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TabTriggers::TabTriggers(MainWindow *parent)
|
||||
: QWidget(parent)
|
||||
, ui(new Ui::TabTriggers)
|
||||
, parent(parent)
|
||||
, thread()
|
||||
, nextupdate()
|
||||
, updt(20)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->treeWidget->setSortingEnabled(false); // sortable triggers are not necessary
|
||||
|
||||
connect(&thread, &AnalysisTriggers::warning, this, &TabTriggers::warning, Qt::BlockingQueuedConnection);
|
||||
connect(&thread, &AnalysisTriggers::itemDone, this, &TabTriggers::onAnalysisItemDone, Qt::BlockingQueuedConnection);
|
||||
connect(&thread, &AnalysisTriggers::finished, this, &TabTriggers::onAnalysisFinished);
|
||||
}
|
||||
|
||||
TabTriggers::~TabTriggers()
|
||||
{
|
||||
thread.stop = true;
|
||||
thread.wait(500);
|
||||
delete ui;
|
||||
}
|
||||
|
||||
bool TabTriggers::event(QEvent *e)
|
||||
{
|
||||
if (e->type() == QEvent::LayoutRequest)
|
||||
{
|
||||
QFontMetrics fm = QFontMetrics(ui->treeWidget->font());
|
||||
ui->treeWidget->setColumnWidth(0, txtWidth(fm) * 24);
|
||||
ui->treeWidget->setColumnWidth(1, txtWidth(fm) * 30);
|
||||
ui->treeWidget->setColumnWidth(2, txtWidth(fm) * 9);
|
||||
ui->treeWidget->setColumnWidth(3, txtWidth(fm) * 9);
|
||||
}
|
||||
return QWidget::event(e);
|
||||
}
|
||||
|
||||
void TabTriggers::save(QSettings&)
|
||||
{
|
||||
}
|
||||
|
||||
void TabTriggers::load(QSettings&)
|
||||
{
|
||||
}
|
||||
|
||||
int TabTriggers::warning(QString text, QMessageBox::StandardButtons buttons)
|
||||
{
|
||||
return warn(parent, text, buttons);
|
||||
}
|
||||
|
||||
void TabTriggers::onAnalysisItemDone(QTreeWidgetItem *item)
|
||||
{
|
||||
qbuf.push_back(item);
|
||||
quint64 ns = elapsed.nsecsElapsed();
|
||||
if (ns > nextupdate)
|
||||
{
|
||||
nextupdate = ns + updt * 1e6;
|
||||
QTimer::singleShot(updt, this, &TabTriggers::onBufferTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
void TabTriggers::onAnalysisFinished()
|
||||
{
|
||||
onBufferTimeout();
|
||||
ui->pushExport->setEnabled(ui->treeWidget->topLevelItemCount() > 0);
|
||||
ui->pushStart->setChecked(false);
|
||||
ui->pushStart->setText(tr("Analyze"));
|
||||
}
|
||||
|
||||
void TabTriggers::onBufferTimeout()
|
||||
{
|
||||
uint64_t t = -elapsed.elapsed();
|
||||
|
||||
if (!qbuf.empty())
|
||||
{
|
||||
ui->treeWidget->setUpdatesEnabled(false);
|
||||
ui->treeWidget->addTopLevelItems(qbuf);
|
||||
ui->treeWidget->setUpdatesEnabled(true);
|
||||
|
||||
QString progress = QString::asprintf(" (%ld/%zu)", thread.idx.load(), thread.seeds.size());
|
||||
ui->pushStart->setText(tr("Stop") + progress);
|
||||
|
||||
qbuf.clear();
|
||||
}
|
||||
|
||||
QApplication::processEvents(); // force processing of events so we can time correctly
|
||||
|
||||
t += elapsed.elapsed();
|
||||
if (8*t > updt)
|
||||
updt = 4*t;
|
||||
nextupdate = elapsed.nsecsElapsed() + 1e6 * updt;
|
||||
}
|
||||
|
||||
void TabTriggers::on_pushStart_clicked()
|
||||
{
|
||||
if (thread.isRunning())
|
||||
{
|
||||
thread.stop = true;
|
||||
return;
|
||||
}
|
||||
updt = 20;
|
||||
nextupdate = 0;
|
||||
elapsed.start();
|
||||
|
||||
parent->getSeed(&thread.wi);
|
||||
thread.conds = parent->formCond->getConditions();
|
||||
thread.seeds.clear();
|
||||
if (ui->comboSeedSource->currentIndex() == 0)
|
||||
thread.seeds.push_back(thread.wi.seed);
|
||||
else
|
||||
thread.seeds = parent->formControl->getResults();
|
||||
|
||||
//ui->treeWidget->setSortingEnabled(false);
|
||||
while (ui->treeWidget->topLevelItemCount() > 0)
|
||||
delete ui->treeWidget->takeTopLevelItem(0);
|
||||
|
||||
ui->pushExport->setEnabled(false);
|
||||
ui->pushStart->setChecked(true);
|
||||
QString progress = QString::asprintf(" (0/%zu)", thread.seeds.size());
|
||||
ui->pushStart->setText(tr("Stop") + progress);
|
||||
thread.start();
|
||||
}
|
||||
|
||||
void TabTriggers::on_treeWidget_itemClicked(QTreeWidgetItem *item, int column)
|
||||
{
|
||||
(void) column;
|
||||
QVariant dat;
|
||||
dat = item->data(0, Qt::UserRole+0);
|
||||
if (dat.isValid())
|
||||
{
|
||||
uint64_t seed = qvariant_cast<uint64_t>(dat);
|
||||
dat = item->data(0, Qt::UserRole+1);
|
||||
int dim = dat.isValid() ? dat.toInt() : DIM_UNDEF;
|
||||
WorldInfo wi;
|
||||
parent->getSeed(&wi);
|
||||
wi.seed = seed;
|
||||
parent->setSeed(wi, dim);
|
||||
}
|
||||
|
||||
dat = item->data(0, Qt::UserRole+2);
|
||||
if (dat.isValid())
|
||||
{
|
||||
Pos p = qvariant_cast<Pos>(dat);
|
||||
parent->getMapView()->setView(p.x+0.5, p.z+0.5);
|
||||
}
|
||||
}
|
||||
|
||||
void TabTriggers::on_pushExpand_clicked()
|
||||
{
|
||||
bool expand = false;
|
||||
for (QTreeWidgetItemIterator it(ui->treeWidget); *it; ++it)
|
||||
if (!(*it)->isExpanded())
|
||||
expand = true;
|
||||
if (expand)
|
||||
ui->treeWidget->expandAll();
|
||||
else
|
||||
ui->treeWidget->collapseAll();
|
||||
}
|
||||
|
||||
static
|
||||
void csvline(QTextStream& stream, const QString& qte, const QString& sep, QStringList& cols)
|
||||
{
|
||||
if (qte.isEmpty())
|
||||
{
|
||||
for (QString& s : cols)
|
||||
if (s.contains(sep))
|
||||
s = "\"" + s + "\"";
|
||||
}
|
||||
stream << qte << cols.join(sep) << qte << "\n";
|
||||
}
|
||||
|
||||
void TabTriggers::on_pushExport_clicked()
|
||||
{
|
||||
QString fnam = QFileDialog::getSaveFileName(
|
||||
this, tr("Export trigger analysis"), parent->prevdir, tr("Text files (*.txt *csv);;Any files (*)"));
|
||||
if (fnam.isEmpty())
|
||||
return;
|
||||
|
||||
QFileInfo finfo(fnam);
|
||||
QFile file(fnam);
|
||||
parent->prevdir = finfo.absolutePath();
|
||||
|
||||
if (!file.open(QIODevice::WriteOnly))
|
||||
{
|
||||
warn(parent, tr("Failed to open file for export:\n\"%1\"").arg(fnam));
|
||||
return;
|
||||
}
|
||||
|
||||
QString qte = parent->config.quote;
|
||||
QString sep = parent->config.separator;
|
||||
|
||||
QTextStream stream(&file);
|
||||
stream << "Sep=" + sep + "\n";
|
||||
sep = qte + sep + qte;
|
||||
|
||||
QStringList header = { tr("seed"), tr("condition"), tr("x"), tr("z") };
|
||||
csvline(stream, qte, sep, header);
|
||||
|
||||
QTreeWidgetItemIterator it(ui->treeWidget);
|
||||
for (; *it; ++it)
|
||||
{
|
||||
QTreeWidgetItem *item = *it;
|
||||
QStringList cols;
|
||||
for (int i = 0, n = item->columnCount(); i < n; i++)
|
||||
{
|
||||
QString s = item->text(i);
|
||||
if (s == "-") s = "";
|
||||
cols.append(s);
|
||||
}
|
||||
csvline(stream, qte, sep, cols);
|
||||
}
|
||||
}
|
||||
|
@ -1,73 +0,0 @@
|
||||
#ifndef TABTRIGGERS_H
|
||||
#define TABTRIGGERS_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QThread>
|
||||
#include <QTreeWidgetItem>
|
||||
|
||||
#include "mainwindow.h"
|
||||
#include "search.h"
|
||||
#include "world.h"
|
||||
|
||||
namespace Ui {
|
||||
class TabTriggers;
|
||||
}
|
||||
|
||||
class AnalysisTriggers : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit AnalysisTriggers(QObject *parent = nullptr)
|
||||
: QThread(parent), conds(),seeds(),wi(),stop(),idx() {}
|
||||
|
||||
virtual void run() override;
|
||||
|
||||
signals:
|
||||
void itemDone(QTreeWidgetItem *item);
|
||||
int warning(QString text, QMessageBox::StandardButtons buttons);
|
||||
|
||||
public:
|
||||
QVector<Condition> conds;
|
||||
std::vector<uint64_t> seeds;
|
||||
WorldInfo wi;
|
||||
std::atomic_bool stop;
|
||||
std::atomic_long idx;
|
||||
};
|
||||
|
||||
|
||||
class TabTriggers : public QWidget, public ISaveTab
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit TabTriggers(MainWindow *parent);
|
||||
~TabTriggers();
|
||||
|
||||
virtual bool event(QEvent *e) override;
|
||||
|
||||
virtual void save(QSettings& settings) override;
|
||||
virtual void load(QSettings& settings) override;
|
||||
|
||||
private slots:
|
||||
int warning(QString text, QMessageBox::StandardButtons buttons);
|
||||
void onAnalysisItemDone(QTreeWidgetItem *item);
|
||||
void onAnalysisFinished();
|
||||
void onBufferTimeout();
|
||||
|
||||
void on_pushStart_clicked();
|
||||
void on_pushExpand_clicked();
|
||||
void on_pushExport_clicked();
|
||||
void on_treeWidget_itemClicked(QTreeWidgetItem *item, int column);
|
||||
|
||||
private:
|
||||
Ui::TabTriggers *ui;
|
||||
MainWindow *parent;
|
||||
AnalysisTriggers thread;
|
||||
|
||||
QElapsedTimer elapsed;
|
||||
uint64_t nextupdate;
|
||||
uint64_t updt;
|
||||
QList<QTreeWidgetItem*> qbuf;
|
||||
};
|
||||
|
||||
#endif // TABTRIGGERS_H
|
@ -1,142 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>TabTriggers</class>
|
||||
<widget class="QWidget" name="TabTriggers">
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="comboSeedSource">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Current seed</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>From matching seeds list</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Seed(s):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QLabel" name="labelDescription">
|
||||
<property name="text">
|
||||
<string>Examine how the conditions are evaluated.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<widget class="QTreeWidget" name="treeWidget">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Monospace</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="dragDropMode">
|
||||
<enum>QAbstractItemView::NoDragDrop</enum>
|
||||
</property>
|
||||
<property name="indentation">
|
||||
<number>12</number>
|
||||
</property>
|
||||
<property name="animated">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="expandsOnDoubleClick">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="headerDefaultSectionSize">
|
||||
<number>100</number>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>seed</string>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Monospace</family>
|
||||
</font>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>condition</string>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Monospace</family>
|
||||
</font>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>x</string>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Monospace</family>
|
||||
</font>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>z</string>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Monospace</family>
|
||||
</font>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0" colspan="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushExport">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Export...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushExpand">
|
||||
<property name="text">
|
||||
<string>Expand all</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushStart">
|
||||
<property name="text">
|
||||
<string>Analyze</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
540
src/widgets.cpp
Normal file
@ -0,0 +1,540 @@
|
||||
#include "widgets.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QStyleOptionSlider>
|
||||
#include <QPainter>
|
||||
#include <QMouseEvent>
|
||||
#include <QBoxLayout>
|
||||
#include <QPropertyAnimation>
|
||||
#include <QVBoxLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QFont>
|
||||
#include <QPushButton>
|
||||
#include <QMessageBox>
|
||||
#include <QSpinBox>
|
||||
#include <QLineEdit>
|
||||
#include <QTextEdit>
|
||||
#include <QParallelAnimationGroup>
|
||||
#include <QToolButton>
|
||||
#include <QFrame>
|
||||
#include <QLabel>
|
||||
#include <QListWidgetItem>
|
||||
|
||||
Collapsible::Collapsible(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, animgroup(new QParallelAnimationGroup(this))
|
||||
, toggleButton(new QToolButton(this))
|
||||
, frameBar(new QFrame(this))
|
||||
, content()
|
||||
, contentHeight()
|
||||
{
|
||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::MinimumExpanding);
|
||||
|
||||
QFont font = toggleButton->font();
|
||||
font.setBold(true);
|
||||
toggleButton->setFont(font);
|
||||
toggleButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
|
||||
toggleButton->setArrowType(Qt::ArrowType::RightArrow);
|
||||
toggleButton->setCheckable(true);
|
||||
|
||||
|
||||
frameBar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
|
||||
frameBar->setFrameShape(QFrame::HLine);
|
||||
|
||||
QVBoxLayout *vbox = new QVBoxLayout();
|
||||
layoutBar = new QHBoxLayout();
|
||||
layoutBar->addWidget(toggleButton, Qt::AlignBottom);
|
||||
layoutBar->addWidget(frameBar, Qt::AlignCenter);
|
||||
layoutBar->setSpacing(5);
|
||||
vbox->addLayout(layoutBar);
|
||||
|
||||
layoutContent = new QHBoxLayout();
|
||||
layoutContent->setContentsMargins(20, 0, 0, 0);
|
||||
vbox->addLayout(layoutContent);
|
||||
|
||||
vbox->setSizeConstraint(QLayout::SetMaximumSize);
|
||||
vbox->setContentsMargins(0, 0, 0, 8);
|
||||
vbox->setSpacing(0);
|
||||
setLayout(vbox);
|
||||
|
||||
connect(toggleButton, &QToolButton::toggled, this, &Collapsible::toggle);
|
||||
connect(animgroup, &QAbstractAnimation::finished, this, &Collapsible::finishAnimation);
|
||||
}
|
||||
|
||||
void Collapsible::toggle(bool collapsed)
|
||||
{
|
||||
if (!content)
|
||||
return;
|
||||
|
||||
int height = content->size().height();
|
||||
if (height)
|
||||
contentHeight = height;
|
||||
|
||||
if (collapsed)
|
||||
{
|
||||
content->setMinimumHeight(0);
|
||||
content->setMaximumHeight(0);
|
||||
toggleButton->setArrowType(Qt::ArrowType::DownArrow);
|
||||
animgroup->setDirection(QAbstractAnimation::Forward);
|
||||
}
|
||||
else
|
||||
{
|
||||
toggleButton->setArrowType(Qt::ArrowType::RightArrow);
|
||||
animgroup->setDirection(QAbstractAnimation::Backward);
|
||||
}
|
||||
|
||||
for (int i = 0, n = animgroup->animationCount(); i < n; i++)
|
||||
{
|
||||
QPropertyAnimation *anim;
|
||||
anim = (QPropertyAnimation*) animgroup->animationAt(i);
|
||||
anim->setStartValue(0);
|
||||
anim->setEndValue(contentHeight);
|
||||
anim->setDuration(200);
|
||||
}
|
||||
|
||||
animgroup->start();
|
||||
}
|
||||
|
||||
void Collapsible::finishAnimation()
|
||||
{
|
||||
if (toggleButton->isChecked())
|
||||
{
|
||||
content->setMinimumHeight(0);
|
||||
content->setMaximumHeight(16777215);
|
||||
}
|
||||
}
|
||||
|
||||
void Collapsible::init(const QString& title, QWidget *widget, bool collapsed)
|
||||
{
|
||||
toggleButton->setText(title);
|
||||
layoutContent->addWidget(widget);
|
||||
contentHeight = widget->sizeHint().height();
|
||||
content = widget;
|
||||
animgroup->addAnimation(new QPropertyAnimation(content, "minimumHeight"));
|
||||
animgroup->addAnimation(new QPropertyAnimation(content, "maximumHeight"));
|
||||
setCollapsed(collapsed);
|
||||
}
|
||||
|
||||
void Collapsible::setCollapsed(bool collapsed)
|
||||
{
|
||||
if (collapsed)
|
||||
{
|
||||
toggleButton->setChecked(false);
|
||||
content->setMinimumHeight(0);
|
||||
content->setMaximumHeight(0);
|
||||
toggleButton->setArrowType(Qt::ArrowType::RightArrow);
|
||||
animgroup->setDirection(QAbstractAnimation::Backward);
|
||||
}
|
||||
else
|
||||
{
|
||||
toggleButton->setChecked(true);
|
||||
content->setMinimumHeight(0);
|
||||
content->setMaximumHeight(16777215);
|
||||
toggleButton->setArrowType(Qt::ArrowType::DownArrow);
|
||||
animgroup->setDirection(QAbstractAnimation::Forward);
|
||||
}
|
||||
animgroup->stop();
|
||||
}
|
||||
|
||||
void Collapsible::setInfo(const QString& title, const QString& text)
|
||||
{
|
||||
QPushButton *button = new QPushButton("", this);
|
||||
button->setStyleSheet(
|
||||
"QPushButton {"
|
||||
" background-color: rgba(255, 255, 255, 0);"
|
||||
" border: none;"
|
||||
" image: url(:/icons/info.png);"
|
||||
" image-position: right;"
|
||||
"}"
|
||||
"QPushButton:hover {"
|
||||
" image: url(:/icons/info_h.png);"
|
||||
"}");
|
||||
int fmh = fontMetrics().height();
|
||||
button->setIconSize(QSize(fmh, fmh));
|
||||
button->setToolTip(tr("Show help"));
|
||||
|
||||
connect(button, SIGNAL(clicked()), this, SLOT(showInfo()));
|
||||
|
||||
layoutBar->addWidget(button, Qt::AlignLeft);
|
||||
infotitle = title;
|
||||
infomsg = text;
|
||||
}
|
||||
|
||||
void Collapsible::showInfo()
|
||||
{
|
||||
// windows plays an annoying sound when you use QMessageBox::information()
|
||||
QMessageBox mb(this);
|
||||
mb.setIcon(QMessageBox::Information);
|
||||
mb.setWindowTitle(infotitle);
|
||||
mb.setText(infomsg);
|
||||
mb.exec();
|
||||
}
|
||||
|
||||
RangeSlider::RangeSlider(QWidget *parent, int vmin, int vmax)
|
||||
: QSlider(parent)
|
||||
, vmin(vmin)
|
||||
, vmax(vmax)
|
||||
, pos0(vmin)
|
||||
, pos1(vmax)
|
||||
, holding(0)
|
||||
{
|
||||
setRange(vmin, vmax);
|
||||
setOrientation(Qt::Horizontal);
|
||||
|
||||
// drawComplexControl() draws the background on every call if there is a stylesheet
|
||||
// to mitigate this, we set the background transparent
|
||||
setStyleSheet(
|
||||
"QSlider { background-color: rgba(180, 180, 180, 0); }\n"
|
||||
"QSlider::sub-page { background-color: rgba(255, 255, 255, 0); }"
|
||||
);
|
||||
//colinner = palette().color(QPalette::Highlight);
|
||||
//colouter = QColor(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
RangeSlider::~RangeSlider()
|
||||
{
|
||||
}
|
||||
|
||||
void RangeSlider::paintEvent(QPaintEvent *)
|
||||
{
|
||||
QPainter painter(this);
|
||||
|
||||
QStyleOptionSlider opt;
|
||||
initStyleOption(&opt);
|
||||
|
||||
// draw the back groove of the slider without range highlighting
|
||||
opt.subControls = QStyle::SC_SliderGroove;
|
||||
opt.sliderValue = opt.sliderPosition = vmin;
|
||||
style()->drawComplexControl(QStyle::CC_Slider, &opt, &painter, this);
|
||||
|
||||
// draw the range highlighting between the handles
|
||||
QRect groove = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderGroove, this);
|
||||
opt.sliderValue = opt.sliderPosition = pos0;
|
||||
QRect handle0 = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, this);
|
||||
opt.sliderValue = opt.sliderPosition = pos1;
|
||||
QRect handle1 = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, this);
|
||||
|
||||
if (colinner.isValid())
|
||||
{
|
||||
painter.setBrush(QBrush(colinner));
|
||||
painter.setPen(QPen(colinner, 0));
|
||||
int x0 = handle0.center().x();
|
||||
int x1 = handle1.center().x();
|
||||
int y = handle0.center().y() - 1;
|
||||
QRect span = QRect(x0, y, x1-x0, 3);
|
||||
painter.drawRect(groove.intersected(span));
|
||||
}
|
||||
if (colouter.isValid())
|
||||
{
|
||||
painter.setBrush(QBrush(colouter));
|
||||
painter.setPen(QPen(colouter, 0));
|
||||
int x0 = handle0.center().x();
|
||||
int x1 = handle1.center().x();
|
||||
int y = handle0.center().y() - 1;
|
||||
QRect left = QRect(groove.x()+1, y, x0-groove.x()-2, 3);
|
||||
painter.drawRect(groove.intersected(left));
|
||||
QRect right = QRect(x1+1, y, groove.right()-x1-2, 3);
|
||||
painter.drawRect(groove.intersected(right));
|
||||
}
|
||||
|
||||
int pmin = pos0 < pos1 ? pos0 : pos1;
|
||||
int pmax = pos0 > pos1 ? pos0 : pos1;
|
||||
// draw handles
|
||||
opt.subControls = QStyle::SC_SliderHandle;
|
||||
opt.sliderValue = opt.sliderPosition = pmax;
|
||||
style()->drawComplexControl(QStyle::CC_Slider, &opt, &painter, this);
|
||||
opt.sliderValue = opt.sliderPosition = pmin;
|
||||
style()->drawComplexControl(QStyle::CC_Slider, &opt, &painter, this);
|
||||
}
|
||||
|
||||
void RangeSlider::mousePressEvent(QMouseEvent *e)
|
||||
{
|
||||
if (e->button() == Qt::LeftButton)
|
||||
{
|
||||
// determine which handle we are holding if any
|
||||
QStyleOptionSlider opt;
|
||||
initStyleOption(&opt);
|
||||
QStyle::SubControl hit;
|
||||
holding = 0;
|
||||
opt.sliderValue = opt.sliderPosition = pos0;
|
||||
hit = style()->hitTestComplexControl(QStyle::CC_Slider, &opt, e->pos(), this);
|
||||
if (hit == QStyle::SC_SliderHandle)
|
||||
holding = -1;
|
||||
opt.sliderValue = opt.sliderPosition = pos1;
|
||||
hit = style()->hitTestComplexControl(QStyle::CC_Slider, &opt, e->pos(), this);
|
||||
if (hit == QStyle::SC_SliderHandle)
|
||||
holding = +1;
|
||||
}
|
||||
|
||||
QSlider::mousePressEvent(e);
|
||||
}
|
||||
|
||||
void RangeSlider::mouseReleaseEvent(QMouseEvent *e)
|
||||
{
|
||||
holding = 0;
|
||||
if (pos0 > pos1)
|
||||
{
|
||||
int tmp = pos0;
|
||||
pos0 = pos1;
|
||||
pos1 = tmp;
|
||||
}
|
||||
emit valueChanged(0);
|
||||
QSlider::mouseReleaseEvent(e);
|
||||
}
|
||||
|
||||
void RangeSlider::wheelEvent(QWheelEvent *e)
|
||||
{
|
||||
QStyleOptionSlider opt;
|
||||
initStyleOption(&opt);
|
||||
|
||||
QRect groove = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderGroove, this);
|
||||
|
||||
int delta = e->angleDelta().y() / 8 / 15;
|
||||
int x;
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
|
||||
x = e->x() - groove.x();
|
||||
#else
|
||||
x = (int)e->position().x() - groove.x();
|
||||
#endif
|
||||
x = style()->sliderValueFromPosition(vmin, vmax, x, groove.width());
|
||||
|
||||
int h = 0;
|
||||
if (x < pos0)
|
||||
h = -1;
|
||||
else if (x > pos1)
|
||||
h = +1;
|
||||
else if (abs(pos0 - x) < abs(pos1 - x))
|
||||
h = -1;
|
||||
else if (abs(pos0 - x) > abs(pos1 - x))
|
||||
h = +1;
|
||||
|
||||
if (e->modifiers() & Qt::ControlModifier)
|
||||
delta *= 50;
|
||||
|
||||
if (h < 0)
|
||||
{
|
||||
pos0 += delta;
|
||||
if (pos0 < vmin) pos0 = vmin;
|
||||
if (pos0 > pos1) pos0 = pos1;
|
||||
emit valueChanged(pos0);
|
||||
}
|
||||
else
|
||||
{
|
||||
pos1 += delta;
|
||||
if (pos1 > vmax) pos1 = vmax;
|
||||
if (pos1 < pos0) pos1 = pos0;
|
||||
emit valueChanged(pos1);
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void RangeSlider::mouseMoveEvent(QMouseEvent *e)
|
||||
{
|
||||
if (holding == 0)
|
||||
return;
|
||||
|
||||
QStyleOptionSlider opt;
|
||||
initStyleOption(&opt);
|
||||
|
||||
opt.sliderValue = opt.sliderPosition = holding < 0 ? pos0 : pos1;
|
||||
|
||||
QRect groove = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderGroove, this);
|
||||
|
||||
int x = e->x() - groove.x();
|
||||
x = style()->sliderValueFromPosition(vmin, vmax, x, groove.width());
|
||||
|
||||
if (holding < 0)
|
||||
pos0 = x;
|
||||
else
|
||||
pos1 = x;
|
||||
|
||||
emit valueChanged(x);
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
LabeledRange::LabeledRange(QWidget *parent, int vmin, int vmax)
|
||||
: QWidget(parent)
|
||||
{
|
||||
slider = new RangeSlider(this, vmin, vmax);
|
||||
minlabel = new QLabel(this);
|
||||
maxlabel = new QLabel(this);
|
||||
minlabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
||||
maxlabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
|
||||
int w = fontMetrics().tightBoundingRect("+012345").width();
|
||||
minlabel->setFixedWidth(w);
|
||||
maxlabel->setFixedWidth(w);
|
||||
|
||||
QBoxLayout *l = new QBoxLayout(QBoxLayout::LeftToRight, this);
|
||||
l->addWidget(minlabel);
|
||||
l->addWidget(slider);
|
||||
l->addWidget(maxlabel);
|
||||
l->setContentsMargins(0, 0, 0, 0);
|
||||
setLayout(l);
|
||||
|
||||
connect(slider, SIGNAL(valueChanged(int)), this, SLOT(rangeChanged(void)));
|
||||
rangeChanged();
|
||||
}
|
||||
|
||||
LabeledRange::~LabeledRange()
|
||||
{
|
||||
}
|
||||
|
||||
void LabeledRange::setLimitText(QString min, QString max)
|
||||
{
|
||||
mintxt = min;
|
||||
maxtxt = max;
|
||||
rangeChanged();
|
||||
}
|
||||
|
||||
void LabeledRange::setValues(int p0, int p1)
|
||||
{
|
||||
slider->pos0 = p0;
|
||||
slider->pos1 = p1;
|
||||
slider->update();
|
||||
rangeChanged();
|
||||
}
|
||||
|
||||
void LabeledRange::setHighlight(QColor inner, QColor outer)
|
||||
{
|
||||
slider->colinner = inner;
|
||||
slider->colouter = outer;
|
||||
slider->update();
|
||||
}
|
||||
|
||||
void LabeledRange::rangeChanged()
|
||||
{
|
||||
int pmin = slider->pos0 < slider->pos1 ? slider->pos0 : slider->pos1;
|
||||
int pmax = slider->pos0 > slider->pos1 ? slider->pos0 : slider->pos1;
|
||||
minlabel->setText(QString::number(pmin));
|
||||
maxlabel->setText(QString::number(pmax));
|
||||
if (!mintxt.isEmpty() && pmin == slider->vmin)
|
||||
minlabel->setText(mintxt);
|
||||
if (!maxtxt.isEmpty() && pmax == slider->vmax)
|
||||
maxlabel->setText(maxtxt);
|
||||
emit onRangeChange();
|
||||
}
|
||||
|
||||
|
||||
QSize CoordEdit::sizeHint() const
|
||||
{
|
||||
QSize size = QLineEdit::minimumSizeHint();
|
||||
QFontMetrics fm(font());
|
||||
size.setWidth(size.width() + txtWidth(fm, "-30000000"));
|
||||
return size;
|
||||
}
|
||||
|
||||
SpinExclude::SpinExclude(QWidget *parent)
|
||||
: QSpinBox(parent)
|
||||
{
|
||||
setMinimum(-1);
|
||||
QObject::connect(this, SIGNAL(valueChanged(int)), this, SLOT(change(int)), Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
SpinExclude::~SpinExclude()
|
||||
{
|
||||
}
|
||||
|
||||
int SpinExclude::valueFromText(const QString &text) const
|
||||
{
|
||||
return QSpinBox::valueFromText(text.section(" ", 0, 0));
|
||||
}
|
||||
|
||||
QString SpinExclude::textFromValue(int value) const
|
||||
{
|
||||
QString txt = QSpinBox::textFromValue(value);
|
||||
if (value == 0)
|
||||
txt += " " + tr("(ignore)");
|
||||
if (value == -1)
|
||||
txt += " " + tr("(exclude)");
|
||||
return txt;
|
||||
}
|
||||
|
||||
void SpinExclude::change(int v)
|
||||
{
|
||||
const char *style = "";
|
||||
if (v < 0)
|
||||
style = "background: #28ff0000";
|
||||
if (v > 0)
|
||||
style = "background: #2800ff00";
|
||||
setStyleSheet(style);
|
||||
findChild<QLineEdit*>()->deselect();
|
||||
}
|
||||
|
||||
|
||||
SpinInstances::SpinInstances(QWidget *parent)
|
||||
: QSpinBox(parent)
|
||||
{
|
||||
setRange(0, 99);
|
||||
}
|
||||
|
||||
SpinInstances::~SpinInstances()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int SpinInstances::valueFromText(const QString &text) const
|
||||
{
|
||||
return QSpinBox::valueFromText(text.section(" ", 0, 0));
|
||||
}
|
||||
|
||||
QString SpinInstances::textFromValue(int value) const
|
||||
{
|
||||
QString txt = QSpinBox::textFromValue(value);
|
||||
if (value == 0)
|
||||
txt += " " + tr("(exclude)");
|
||||
if (value > 1)
|
||||
txt += " " + tr("(cluster)");
|
||||
return txt;
|
||||
}
|
||||
|
||||
|
||||
ComboBoxDelegate::ComboBoxDelegate(QObject *parent, QComboBox *cmb)
|
||||
: QStyledItemDelegate(parent)
|
||||
, combo(cmb)
|
||||
{
|
||||
}
|
||||
|
||||
ComboBoxDelegate::~ComboBoxDelegate()
|
||||
{
|
||||
}
|
||||
|
||||
static bool isSeparator(const QModelIndex &index)
|
||||
{
|
||||
return index.data(Qt::AccessibleDescriptionRole).toString() == QString::fromLatin1("separator");
|
||||
}
|
||||
|
||||
void ComboBoxDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
{
|
||||
if (isSeparator(index))
|
||||
{
|
||||
QStyleOptionViewItem opt = option;
|
||||
if (const QAbstractItemView *view = qobject_cast<const QAbstractItemView*>(option.widget))
|
||||
opt.rect.setWidth(view->viewport()->width());
|
||||
combo->style()->drawPrimitive(QStyle::PE_IndicatorToolBarSeparator, &opt, painter, combo);
|
||||
}
|
||||
else
|
||||
{
|
||||
QStyledItemDelegate::paint(painter, option, index);
|
||||
}
|
||||
}
|
||||
|
||||
QSize ComboBoxDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
{
|
||||
if (isSeparator(index))
|
||||
{
|
||||
int pm = combo->style()->pixelMetric(QStyle::PM_DefaultFrameWidth, nullptr, combo) + 4;
|
||||
return QSize(pm, pm);
|
||||
}
|
||||
QSize size = QStyledItemDelegate::sizeHint(option, index);
|
||||
int h = size.height();
|
||||
int hicon = combo->iconSize().height() + 1;
|
||||
int hfont = combo->fontMetrics().height() + 4;
|
||||
if (h < hicon) h = hicon;
|
||||
if (h < hfont) h = hfont;
|
||||
if (size.height() < h)
|
||||
size.setHeight(h);
|
||||
return size;
|
||||
}
|
143
src/widgets.h
Normal file
@ -0,0 +1,143 @@
|
||||
#ifndef WIDGETS_H
|
||||
#define WIDGETS_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QSlider>
|
||||
#include <QComboBox>
|
||||
#include <QStyledItemDelegate>
|
||||
#include <QSpinBox>
|
||||
#include <QLineEdit>
|
||||
|
||||
class QParallelAnimationGroup;
|
||||
class QToolButton;
|
||||
class QFrame;
|
||||
class QHBoxLayout;
|
||||
class QLabel;
|
||||
|
||||
class Collapsible : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit Collapsible(QWidget *parent = nullptr);
|
||||
void init(const QString& title, QWidget *widget, bool collapsed);
|
||||
void setInfo(const QString& title, const QString& text);
|
||||
void setCollapsed(bool collapsed); // without animation
|
||||
|
||||
public slots:
|
||||
void toggle(bool collapsed);
|
||||
void finishAnimation();
|
||||
void showInfo();
|
||||
|
||||
public:
|
||||
QParallelAnimationGroup* animgroup;
|
||||
QToolButton* toggleButton;
|
||||
QFrame* frameBar;
|
||||
QWidget *content;
|
||||
QHBoxLayout *layoutBar;
|
||||
QHBoxLayout *layoutContent;
|
||||
|
||||
int contentHeight;
|
||||
QString infotitle;
|
||||
QString infomsg;
|
||||
};
|
||||
|
||||
class RangeSlider : public QSlider
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
RangeSlider(QWidget *parent = nullptr, int vmin = 0, int vmax = 100);
|
||||
virtual ~RangeSlider();
|
||||
|
||||
virtual void paintEvent(QPaintEvent *e) override;
|
||||
virtual void wheelEvent(QWheelEvent *e) override;
|
||||
virtual void mousePressEvent(QMouseEvent *e) override;
|
||||
virtual void mouseReleaseEvent(QMouseEvent *e) override;
|
||||
virtual void mouseMoveEvent(QMouseEvent *e) override;
|
||||
|
||||
int vmin, vmax;
|
||||
int pos0, pos1;
|
||||
int holding;
|
||||
QColor colinner, colouter;
|
||||
};
|
||||
|
||||
class LabeledRange : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
LabeledRange(QWidget *parent = nullptr, int vmin = 0, int vmax = 10);
|
||||
virtual ~LabeledRange();
|
||||
|
||||
void setValues(int p0, int p1);
|
||||
void setLimitText(QString min, QString max);
|
||||
void setHighlight(QColor inner, QColor outer);
|
||||
|
||||
public slots:
|
||||
void rangeChanged();
|
||||
|
||||
signals:
|
||||
void onRangeChange();
|
||||
|
||||
public:
|
||||
RangeSlider *slider;
|
||||
QLabel *minlabel, *maxlabel;
|
||||
QString mintxt, maxtxt;
|
||||
};
|
||||
|
||||
|
||||
// QLineEdit defaults to a style hint width 17 characters, which is too long for coordinates
|
||||
class CoordEdit : public QLineEdit
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CoordEdit(QWidget *parent = nullptr) : QLineEdit(parent) {}
|
||||
virtual QSize sizeHint() const override;
|
||||
};
|
||||
|
||||
class SpinExclude : public QSpinBox
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
SpinExclude(QWidget *parent = nullptr);
|
||||
virtual ~SpinExclude();
|
||||
virtual int valueFromText(const QString &text) const override;
|
||||
virtual QString textFromValue(int value) const override;
|
||||
|
||||
public slots:
|
||||
void change(int v);
|
||||
};
|
||||
|
||||
class SpinInstances : public QSpinBox
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
SpinInstances(QWidget *parent = nullptr);
|
||||
virtual ~SpinInstances();
|
||||
virtual int valueFromText(const QString &text) const override;
|
||||
virtual QString textFromValue(int value) const override;
|
||||
};
|
||||
|
||||
// QComboBox uses QItemDelegate, which would not support styles
|
||||
class ComboBoxDelegate : public QStyledItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ComboBoxDelegate(QObject *parent, QComboBox *cmb);
|
||||
virtual ~ComboBoxDelegate();
|
||||
virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||
virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||
|
||||
private:
|
||||
QComboBox *combo;
|
||||
};
|
||||
|
||||
class StyledComboBox : public QComboBox
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
StyledComboBox(QWidget *parent) : QComboBox(parent)
|
||||
{
|
||||
setItemDelegate(new ComboBoxDelegate(parent, this));
|
||||
}
|
||||
};
|
||||
|
||||
#endif // WIDGETS_H
|
@ -1275,6 +1275,14 @@ void QWorld::draw(QPainter& painter, int vw, int vh, qreal focusx, qreal focusz,
|
||||
}
|
||||
}
|
||||
|
||||
if (imgbuf.width() != vw || imgbuf.height() != vh)
|
||||
{
|
||||
imgbuf = QImage(vw, vh, QImage::Format_Indexed8);
|
||||
imgbuf.setColor(0, qRgba(0, 0, 0, 0));
|
||||
imgbuf.setColor(1, qRgba(255, 255, 255, 96));
|
||||
imgbuf.setColor(2, qRgba(180, 64, 192, 255));
|
||||
}
|
||||
|
||||
for (int sopt = D_DESERT; sopt < D_SPAWN; sopt++)
|
||||
{
|
||||
Level& l = lvs[sopt];
|
||||
@ -1287,11 +1295,8 @@ void QWorld::draw(QPainter& painter, int vw, int vh, qreal focusx, qreal focusz,
|
||||
}
|
||||
|
||||
std::map<const QPixmap*, std::vector<QPainter::PixmapFragment>> frags;
|
||||
QImage bufimg = QImage(vw, vh, QImage::Format_Indexed8);
|
||||
bufimg.setColor(0, qRgba(0, 0, 0, 0));
|
||||
bufimg.setColor(1, qRgba(255, 255, 255, 96));
|
||||
bufimg.setColor(2, qRgba(180, 64, 192, 255));
|
||||
bufimg.fill(0);
|
||||
bool imgbuf_used = false;
|
||||
imgbuf.fill(0);
|
||||
|
||||
for (Quad *q : l.cells)
|
||||
{
|
||||
@ -1384,8 +1389,11 @@ void QWorld::draw(QPainter& painter, int vw, int vh, qreal focusx, qreal focusz,
|
||||
if (q > r*r) continue;
|
||||
int x = floor(d.x() + i);
|
||||
int z = floor(d.y() + j);
|
||||
if (bufimg.rect().contains(x, z))
|
||||
bufimg.setPixel(x, z, q >= 2 ? 1 : 2);
|
||||
if (imgbuf.rect().contains(x, z))
|
||||
{
|
||||
imgbuf.setPixel(x, z, q >= 2 ? 1 : 2);
|
||||
imgbuf_used = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
@ -1410,7 +1418,8 @@ void QWorld::draw(QPainter& painter, int vw, int vh, qreal focusx, qreal focusz,
|
||||
}
|
||||
}
|
||||
|
||||
painter.drawImage(QPoint(0, 0), bufimg);
|
||||
if (imgbuf_used)
|
||||
painter.drawImage(QPoint(0, 0), imgbuf);
|
||||
for (auto& it : frags)
|
||||
painter.drawPixmapFragments(it.second.data(), it.second.size(), *it.first);
|
||||
}
|
||||
|
@ -210,10 +210,13 @@ public:
|
||||
// isdel is a flag for the worker thread to stop
|
||||
std::atomic_bool isdel;
|
||||
|
||||
// slime overlay
|
||||
// slime overlay (pixel chunks)
|
||||
QImage slimeimg;
|
||||
long slimex, slimez;
|
||||
|
||||
// overlay (visual pixels) for geodes
|
||||
QImage imgbuf;
|
||||
|
||||
// shapes to overlay
|
||||
std::vector<Shape> shapes;
|
||||
|
||||
|