add StateIcon

This commit is contained in:
2024-03-24 22:38:52 +03:00
parent 47420cf19a
commit 592c17e1c7
8 changed files with 598 additions and 1 deletions

View File

@@ -3,7 +3,7 @@ cmake_policy(SET CMP0017 NEW) # need include() with .cmake
cmake_policy(SET CMP0072 NEW) # FindOpenGL prefers GLVND by default cmake_policy(SET CMP0072 NEW) # FindOpenGL prefers GLVND by default
project(QAD) project(QAD)
set(QAD_MAJOR 2) set(QAD_MAJOR 2)
set(QAD_MINOR 25) set(QAD_MINOR 26)
set(QAD_REVISION 0) set(QAD_REVISION 0)
set(QAD_SUFFIX ) set(QAD_SUFFIX )
set(QAD_COMPANY SHS) set(QAD_COMPANY SHS)

View File

@@ -17,6 +17,7 @@
#include "scroll_spin_boxplugin.h" #include "scroll_spin_boxplugin.h"
#include "shortcutsplugin.h" #include "shortcutsplugin.h"
#include "spinsliderplugin.h" #include "spinsliderplugin.h"
#include "stateiconplugin.h"
QADWidgets::QADWidgets(QObject * parent): QObject(parent) { QADWidgets::QADWidgets(QObject * parent): QObject(parent) {
@@ -37,6 +38,7 @@ QADWidgets::QADWidgets(QObject * parent): QObject(parent) {
m_widgets.append(new ImageViewPlugin(this)); m_widgets.append(new ImageViewPlugin(this));
m_widgets.append(new ScrollSpinBoxPlugin(this)); m_widgets.append(new ScrollSpinBoxPlugin(this));
m_widgets.append(new RangeSliderPlugin(this)); m_widgets.append(new RangeSliderPlugin(this));
m_widgets.append(new StateIconPlugin(this));
} }

View File

@@ -0,0 +1,191 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>StateIconMenuExtension</class>
<widget class="QDialog" name="StateIconMenuExtension">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>576</width>
<height>464</height>
</rect>
</property>
<property name="windowTitle">
<string>Select variables</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QTreeWidget" name="tree">
<property name="selectionMode">
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="horizontalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="rootIsDecorated">
<bool>false</bool>
</property>
<property name="itemsExpandable">
<bool>false</bool>
</property>
<property name="expandsOnDoubleClick">
<bool>false</bool>
</property>
<column>
<property name="text">
<string>State</string>
</property>
</column>
<column>
<property name="text">
<string>Text</string>
</property>
</column>
<column>
<property name="text">
<string>Icon</string>
</property>
</column>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QToolButton" name="buttonAdd">
<property name="toolTip">
<string>Add</string>
</property>
<property name="icon">
<iconset resource="../../piqt_utils/qad_piqt_widgets.qrc">
<normaloff>:/icons/list-add.png</normaloff>:/icons/list-add.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="buttonDel">
<property name="toolTip">
<string>Remove selected</string>
</property>
<property name="icon">
<iconset resource="../../blockview/qad_blockview.qrc">
<normaloff>:/icons/edit-delete.png</normaloff>:/icons/edit-delete.png</iconset>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>5</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QToolButton" name="buttonClear">
<property name="toolTip">
<string>Clear</string>
</property>
<property name="icon">
<iconset resource="../../application/qad_application.qrc">
<normaloff>:/icons/edit-clear.png</normaloff>:/icons/edit-clear.png</iconset>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="../../application/qad_application.qrc"/>
<include location="../../blockview/qad_blockview.qrc"/>
<include location="../../piqt_utils/qad_piqt_widgets.qrc"/>
</resources>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>StateIconMenuExtension</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>517</x>
<y>606</y>
</hint>
<hint type="destinationlabel">
<x>526</x>
<y>629</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>StateIconMenuExtension</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>470</x>
<y>599</y>
</hint>
<hint type="destinationlabel">
<x>464</x>
<y>631</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonClear</sender>
<signal>clicked()</signal>
<receiver>tree</receiver>
<slot>clear()</slot>
<hints>
<hint type="sourcelabel">
<x>590</x>
<y>140</y>
</hint>
<hint type="destinationlabel">
<x>516</x>
<y>149</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -0,0 +1,177 @@
#include "stateiconplugin.h"
#include "ui_stateiconmenuextension.h"
#include <QAction>
#include <QDesignerFormEditorInterface>
#include <QDesignerFormWindowCursorInterface>
#include <QDesignerFormWindowInterface>
#include <QExtensionManager>
#include <QtCore/QtPlugin>
#include <private/qtresourceview_p.h>
enum Column {
cState,
cText,
cIcon
};
StateIconMenuExtension::StateIconMenuExtension(StateIcon * widget_, QObject *): QDialog(), ui(new Ui::StateIconMenuExtension) {
ui->setupUi(this);
widget = widget_;
icon_command = QIcon(":/icons/code-function.png");
action_default = new QAction("Edit states ...", this);
connect(action_default, SIGNAL(triggered(bool)), this, SLOT(action_default_triggered()));
}
StateIconMenuExtension::~StateIconMenuExtension() {
delete ui;
}
QAction * StateIconMenuExtension::preferredEditAction() const {
return action_default;
}
QList<QAction *> StateIconMenuExtension::taskActions() const {
return {action_default};
}
void StateIconMenuExtension::accept() {
widget->clearStates();
for (int i = 0; i < ui->tree->topLevelItemCount(); ++i) {
QTreeWidgetItem * ti = ui->tree->topLevelItem(i);
widget->addState(ti->text(cState).toInt(), ti->text(cText), ti->text(cIcon));
}
QDesignerFormWindowInterface * formWindow = QDesignerFormWindowInterface::findFormWindow(widget);
if (formWindow) {
formWindow->cursor()->setProperty("rawStates", widget->saveStates());
}
QDialog::accept();
}
void StateIconMenuExtension::on_buttonAdd_clicked() {
auto ti = new QTreeWidgetItem({"0"});
ti->setFlags(ti->flags() | Qt::ItemIsEditable);
ui->tree->addTopLevelItem(ti);
ui->tree->editItem(ti, cState);
}
void StateIconMenuExtension::on_buttonDel_clicked() {
qDeleteAll(ui->tree->selectedItems());
}
void StateIconMenuExtension::on_tree_itemClicked(QTreeWidgetItem * item, int column) {
if (!item) return;
Qt::ItemFlags f = item->flags();
f.setFlag(Qt::ItemIsEditable, column != cIcon);
item->setFlags(f);
}
void StateIconMenuExtension::on_tree_itemDoubleClicked(QTreeWidgetItem * item, int column) {
if (!item || column != cIcon) return;
QDesignerFormWindowInterface * formWindow = QDesignerFormWindowInterface::findFormWindow(widget);
if (formWindow) {
QtResourceViewDialog dlg(formWindow->core());
dlg.selectResource(item->text(cIcon));
if (dlg.exec() == QDialog::Accepted) {
QString ni = dlg.selectedResource();
item->setText(cIcon, ni);
item->setIcon(cIcon, QIcon(ni));
}
}
}
void StateIconMenuExtension::action_default_triggered() {
ui->tree->clear();
auto states = widget->allStates();
for (auto s: states) {
QTreeWidgetItem * ti = new QTreeWidgetItem();
ti->setText(cState, QString::number(s));
ti->setText(cText, widget->stateText(s));
ti->setText(cIcon, widget->stateIcon(s));
ti->setIcon(cIcon, QIcon(widget->stateIcon(s)));
ui->tree->addTopLevelItem(ti);
}
exec();
}
QObject * StateIconTaskMenuFactory::createExtension(QObject * object, const QString & iid, QObject * parent) const {
if (iid != Q_TYPEID(QDesignerTaskMenuExtension)) return 0;
if (StateIcon * w = qobject_cast<StateIcon *>(object)) return new StateIconMenuExtension(w, parent);
return nullptr;
}
StateIconPlugin::StateIconPlugin(QObject * parent): QObject(parent) {
m_initialized = false;
}
void StateIconPlugin::initialize(QDesignerFormEditorInterface * core) {
if (m_initialized) return;
QExtensionManager * manager = core->extensionManager();
Q_ASSERT(manager != 0);
manager->registerExtensions(new StateIconTaskMenuFactory(manager), Q_TYPEID(QDesignerTaskMenuExtension));
m_initialized = true;
}
bool StateIconPlugin::isInitialized() const {
return m_initialized;
}
QWidget * StateIconPlugin::createWidget(QWidget * parent) {
return new StateIcon(parent);
}
QString StateIconPlugin::name() const {
return QLatin1String("StateIcon");
}
QString StateIconPlugin::group() const {
return QLatin1String("Display Widgets");
}
QIcon StateIconPlugin::icon() const {
return QIcon(":/icons/led_on.png");
}
QString StateIconPlugin::toolTip() const {
return QLatin1String("StateIcon");
}
QString StateIconPlugin::whatsThis() const {
return QLatin1String("StateIcon");
}
bool StateIconPlugin::isContainer() const {
return false;
}
QString StateIconPlugin::domXml() const {
return QLatin1String("<widget class=\"StateIcon\" name=\"stateIcon\">\n</widget>\n");
}
QString StateIconPlugin::includeFile() const {
return QLatin1String("stateicon.h");
}

View File

@@ -0,0 +1,90 @@
#ifndef stateiconplugin_H
#define stateiconplugin_H
#include <QObject>
#if QT_VERSION >= 0x050000
# include <QtUiPlugin/QDesignerCustomWidgetInterface>
#else
# include <QDesignerCustomWidgetInterface>
#endif
#include "stateicon.h"
#include <QDesignerPropertyEditorInterface>
#include <QDesignerTaskMenuExtension>
#include <QDialog>
#include <QExtensionFactory>
#include <QTreeWidget>
namespace Ui {
class StateIconMenuExtension;
}
class StateIconMenuExtension
: public QDialog
, public QDesignerTaskMenuExtension {
Q_OBJECT
Q_INTERFACES(QDesignerTaskMenuExtension)
public:
StateIconMenuExtension(StateIcon * widget, QObject * parent);
~StateIconMenuExtension();
QAction * preferredEditAction() const override;
QList<QAction *> taskActions() const override;
public slots:
void accept() override;
private slots:
void on_tree_itemClicked(QTreeWidgetItem * item, int column);
void on_tree_itemDoubleClicked(QTreeWidgetItem * item, int column);
void on_buttonAdd_clicked();
void on_buttonDel_clicked();
void action_default_triggered();
private:
Ui::StateIconMenuExtension * ui;
StateIcon * widget;
QAction * action_default;
QIcon icon_command;
};
class StateIconTaskMenuFactory: public QExtensionFactory {
Q_OBJECT
public:
StateIconTaskMenuFactory(QExtensionManager * parent = 0): QExtensionFactory(parent) { ; }
protected:
QObject * createExtension(QObject * object, const QString & iid, QObject * parent) const;
};
class StateIconPlugin
: public QObject
, public QDesignerCustomWidgetInterface {
Q_OBJECT
Q_INTERFACES(QDesignerCustomWidgetInterface)
public:
StateIconPlugin(QObject * parent = 0);
bool isContainer() const;
bool isInitialized() const;
QIcon icon() const;
QString domXml() const;
QString group() const;
QString includeFile() const;
QString name() const;
QString toolTip() const;
QString whatsThis() const;
QWidget * createWidget(QWidget * parent);
void initialize(QDesignerFormEditorInterface * core);
private:
bool m_initialized;
};
#endif

View File

@@ -40,5 +40,6 @@
<file>../../icons/code-word.png</file> <file>../../icons/code-word.png</file>
<file>../../icons/f1.png</file> <file>../../icons/f1.png</file>
<file>../../icons/scroll_spin.png</file> <file>../../icons/scroll_spin.png</file>
<file>../../icons/led_on.png</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@@ -0,0 +1,77 @@
#include "stateicon.h"
#include "qad_types.h"
#include <QEvent>
#include <QHBoxLayout>
#include <QStyle>
StateIcon::StateIcon(QWidget * parent): IconedLabel(parent) {}
QString StateIcon::saveStates() const {
return QString::fromLatin1(qSerialize(src_states).toBase64());
}
void StateIcon::loadStates(const QString & ba) {
src_states = qDeserialize<QMap<int, QPair<QString, QString>>>(QByteArray::fromBase64(ba.toLatin1()));
prepare();
}
void StateIcon::clearStates() {
src_states.clear();
prepare();
}
void StateIcon::addState(int st, QString text, QIcon icon) {
src_states[st] = QPair<QString, QString>(text, "");
prepared_states[st] = QPair<QString, QIcon>(text, icon);
setState(m_state);
}
void StateIcon::addState(int st, QString text, QString icon_path) {
src_states[st] = QPair<QString, QString>(text, icon_path);
prepared_states[st] = QPair<QString, QIcon>(text, QIcon(icon_path));
setState(m_state);
}
QList<int> StateIcon::allStates() const {
return src_states.keys();
}
QString StateIcon::stateText(int st) const {
return src_states.value(st).first;
}
QString StateIcon::stateIcon(int st) const {
return src_states.value(st).second;
}
void StateIcon::prepare() {
prepared_states.clear();
QMapIterator<int, QPair<QString, QString>> it(src_states);
while (it.hasNext()) {
it.next();
auto & ps(prepared_states[it.key()]);
ps.first = it.value().first;
ps.second = QIcon(it.value().second);
}
setState(m_state);
}
void StateIcon::setState(int newState) {
m_state = newState;
auto cv = prepared_states.value(m_state);
setText(cv.first);
setIcon(cv.second);
}

59
libs/widgets/stateicon.h Normal file
View File

@@ -0,0 +1,59 @@
/*
QAD - Qt ADvanced
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef stateicon_H
#define stateicon_H
#include "iconedlabel.h"
#include "qad_widgets_export.h"
#include <QMap>
class QAD_WIDGETS_EXPORT StateIcon: public IconedLabel {
Q_OBJECT
Q_PROPERTY(QString rawStates READ saveStates WRITE loadStates DESIGNABLE false)
Q_PROPERTY(int state READ state WRITE setState)
public:
explicit StateIcon(QWidget * parent = nullptr);
QString saveStates() const;
void loadStates(const QString & ba);
void clearStates();
void addState(int st, QString text, QIcon icon);
void addState(int st, QString text, QString icon_path);
QList<int> allStates() const;
QString stateText(int st) const;
QString stateIcon(int st) const;
int state() const { return m_state; }
private:
void prepare();
QMap<int, QPair<QString, QString>> src_states;
QMap<int, QPair<QString, QIcon>> prepared_states;
int m_state = 0;
public slots:
void setState(int newState);
};
#endif