Compare commits

...

6 Commits

Author SHA1 Message Date
073d483381 add QAD::loadedLanguage variable 2024-03-29 21:31:39 +03:00
ab2c8d4480 StateIcon improvements 2024-03-26 10:35:08 +03:00
592c17e1c7 add StateIcon 2024-03-24 22:38:52 +03:00
47420cf19a IndexedTimer type 2024-03-24 20:23:15 +03:00
dedd38772e old Qt 2024-03-13 16:40:17 +03:00
50a231a8e7 version 2.25.0
add qad_timers.h in PIQt, IndexedTimer
2024-03-05 19:39:49 +03:00
14 changed files with 711 additions and 3 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
project(QAD)
set(QAD_MAJOR 2)
set(QAD_MINOR 24)
set(QAD_MINOR 26)
set(QAD_REVISION 0)
set(QAD_SUFFIX )
set(QAD_COMPANY SHS)

1
libs/piqt/qad_timers.cpp Normal file
View File

@@ -0,0 +1 @@
#include "qad_timers.h"

79
libs/piqt/qad_timers.h Normal file
View File

@@ -0,0 +1,79 @@
/*
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 qad_timers_H
#define qad_timers_H
#include "qad_utils_export.h"
#include <QDebug>
#include <QMap>
#include <QTimer>
#include <pisystemtime.h>
template<typename Index = int>
class QAD_UTILS_EXPORT IndexedTimer {
public:
~IndexedTimer() {
for (auto & i: timers)
i.destroy();
timers.clear();
}
void setIndexedTimerType(Index index, Qt::TimerType type) { timers[index].type = type; }
void bindIndexedTimer(Index index, std::function<void()> func) { timers[index].func = func; }
void stopIndexedTimer(Index index) {
auto & t(timers[index]);
if (!t.isValid()) return;
t.destroy();
}
void startIndexedTimer(Index index, PISystemTime interval, std::function<void()> func = nullptr) {
stopIndexedTimer(index);
__TimerSlot & t(timers[index]);
if (func) t.func = func;
if (!t.func) {
qDebug() << "[IndexedTimer] startIndexedTimer error: null function!";
return;
}
t.timer = new QTimer();
t.timer->setTimerType(t.type);
QObject::connect(t.timer, &QTimer::timeout, t.func);
t.timer->start(interval.toMilliseconds());
}
bool isIndexedTimerStarted(Index index) const { return timers.value(index).isValid(); }
private:
struct __TimerSlot {
bool isValid() const { return timer; }
void destroy() {
if (!timer) return;
delete timer;
timer = nullptr;
}
std::function<void()> func = nullptr;
QTimer * timer = nullptr;
Qt::TimerType type = Qt::CoarseTimer;
};
QMap<Index, __TimerSlot> timers;
};
#endif

View File

@@ -954,7 +954,7 @@ void PIValueTreeEdit::GridWidgets::simplify(const PIMap<int, int> & map) {
Info info;
info.align = li->alignment();
int pos[4];
lay->getItemPosition(lay->indexOf(li), &(pos[0]), &(pos[1]), &(pos[2]), &(pos[3]));
lay->getItemPosition(lay->indexOf(li->widget()), &(pos[0]), &(pos[1]), &(pos[2]), &(pos[3]));
info.row_span = pos[2];
info.col_span = pos[3];
wa[li->widget()] = info;

View File

@@ -16,6 +16,8 @@
# define MOBILE_VIEW
#endif
QString QAD::loadedLanguage;
class __QADTranslators__ {
public:
@@ -74,6 +76,7 @@ void QAD::loadTranslations(QString lang) {
unloadTranslations();
if (lang.isEmpty()) lang = QLocale().bcp47Name();
QString short_lang = lang.left(2);
loadedLanguage = short_lang;
QStringList dirs = resourcePaths("lang");
QString std_dir = QDir::cleanPath(QLibraryInfo::location(QLibraryInfo::TranslationsPath));
bool has_std = false;

View File

@@ -54,6 +54,7 @@ QAD_UTILS_EXPORT void unloadTranslations();
QAD_UTILS_EXPORT QStringList availableTranslations();
extern QAD_UTILS_EXPORT QString loadedLanguage;
} // namespace QAD

View File

@@ -94,7 +94,7 @@ void IconedLabel::setDirection(IconedLabel::Direction d) {
lay->setContentsMargins(0, 0, 0, 0);
setLayout(lay);
checkSpacing();
update();
updateGeometry();
}

View File

@@ -17,6 +17,7 @@
#include "scroll_spin_boxplugin.h"
#include "shortcutsplugin.h"
#include "spinsliderplugin.h"
#include "stateiconplugin.h"
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 ScrollSpinBoxPlugin(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,185 @@
#include "stateiconplugin.h"
#include "ui_stateiconmenuextension.h"
#include <QAction>
#include <QDesignerFormEditorInterface>
#include <QDesignerFormWindowCursorInterface>
#include <QDesignerFormWindowInterface>
#include <QExtensionManager>
#include <QTimer>
#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) {
auto * ret = new StateIcon(parent);
QDesignerFormWindowInterface * formWindow = QDesignerFormWindowInterface::findFormWindow(parent);
if (formWindow) {
connect(formWindow, &QDesignerFormWindowInterface::resourceFilesChanged, ret, [ret] {
QTimer::singleShot(0, ret, [ret] { ret->loadStates(ret->saveStates()); });
});
}
return ret;
}
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/f1.png</file>
<file>../../icons/scroll_spin.png</file>
<file>../../icons/led_on.png</file>
</qresource>
</RCC>

View File

@@ -0,0 +1,87 @@
#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);
if (m_changeText) setText(cv.first);
if (m_changeIcon) setIcon(cv.second);
}
void StateIcon::setChangeIcon(bool newChangeIcon) {
m_changeIcon = newChangeIcon;
}
void StateIcon::setChangeText(bool newChangeText) {
m_changeText = newChangeText;
}

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

@@ -0,0 +1,68 @@
/*
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)
Q_PROPERTY(bool changeIcon READ isChangeIcon WRITE setChangeIcon)
Q_PROPERTY(bool changeText READ isChangeText WRITE setChangeText)
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;
bool isChangeIcon() const { return m_changeIcon; }
void setChangeIcon(bool newChangeIcon);
bool isChangeText() const { return m_changeText; }
void setChangeText(bool newChangeText);
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;
bool m_changeIcon = true, m_changeText = true;
public slots:
void setState(int newState);
};
#endif