PIValueTreeEdit cut/copy/paste support

EMainWindow saveAs incorrect filename to recent fix
QAD::loadTranslations now also look into standard translation location
This commit is contained in:
2023-04-28 15:33:50 +03:00
parent 4eefbe4e46
commit 76a1b35f14
9 changed files with 289 additions and 261 deletions

View File

@@ -4,7 +4,7 @@ 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 16) set(QAD_MINOR 16)
set(QAD_REVISION 2) set(QAD_REVISION 3)
set(QAD_SUFFIX ) set(QAD_SUFFIX )
set(QAD_COMPANY SHS) set(QAD_COMPANY SHS)
set(QAD_DOMAIN org.SHS) set(QAD_DOMAIN org.SHS)

View File

@@ -416,7 +416,7 @@ bool EMainWindow::saveFile(bool ask) {
bool EMainWindow::saveAsFile() { bool EMainWindow::saveAsFile() {
QString ret = QFileDialog::getSaveFileName(this, tr("Select file to save"), file_name, saveFilter()); QString ret = QFileDialog::getSaveFileName(this, tr("Select file to save"), file_name, saveFilter());
if (ret.isEmpty()) return false; if (ret.isEmpty()) return false;
if (save(ret)) addToRecent(ret); if (save(ret)) addToRecent(file_name);
return true; return true;
} }

View File

@@ -1,11 +1,14 @@
#include "pivaluetree_edit.h" #include "pivaluetree_edit.h"
#include "pijson.h"
#include "piqt.h" #include "piqt.h"
#include "pivaluetree_conversions.h"
#include "pivaluetree_edit_parameters.h" #include "pivaluetree_edit_parameters.h"
#include "pivaluetree_edit_reorder.h" #include "pivaluetree_edit_reorder.h"
#include "pivariant_edit.h" #include "pivariant_edit.h"
#include "ui_pivaluetree_edit_array.h" #include "ui_pivaluetree_edit_array.h"
#include <QClipboard>
#include <QEvent> #include <QEvent>
#include <QFormLayout> #include <QFormLayout>
#include <QGroupBox> #include <QGroupBox>
@@ -19,6 +22,20 @@ using Attribute = PIValueTree::Attribute;
const char property_name[] = "__name__"; const char property_name[] = "__name__";
class ToolButton: public QToolButton {
public:
ToolButton(QWidget * parent = nullptr): QToolButton(parent) {}
void setPressHandler(std::function<void()> f) { press_handler = f; }
protected:
void mousePressEvent(QMouseEvent * e) override {
if (press_handler) press_handler();
QToolButton::mousePressEvent(e);
}
std::function<void()> press_handler;
};
class GroupBox: public QGroupBox { class GroupBox: public QGroupBox {
public: public:
GroupBox(QWidget * content = nullptr): QGroupBox() { GroupBox(QWidget * content = nullptr): QGroupBox() {
@@ -239,8 +256,7 @@ void PIValueTreeEdit::applyValues() const {
} }
void PIValueTreeEdit::actionTriggered(QToolButton * button, const PIString & vn, QAction * a) { void PIValueTreeEdit::actionRename(QToolButton * button, const PIString & vn) {
if (a == widget_params->actionRename) {
PIString nn = Q2PIString(QInputDialog::getText(nullptr, tr("Rename"), tr("Input new name:"), QLineEdit::Normal, PI2QString(vn))); PIString nn = Q2PIString(QInputDialog::getText(nullptr, tr("Rename"), tr("Input new name:"), QLineEdit::Normal, PI2QString(vn)));
if (nn.isEmpty() || (nn == vn)) return; if (nn.isEmpty() || (nn == vn)) return;
for (const auto & c: current.children()) { for (const auto & c: current.children()) {
@@ -278,9 +294,10 @@ void PIValueTreeEdit::actionTriggered(QToolButton * button, const PIString & vn,
} }
} }
} }
return;
} }
if (a == widget_params->actionRemove) {
void PIValueTreeEdit::actionRemove(QToolButton * button, const PIString & vn) {
current.remove(vn); current.remove(vn);
if (tab_widget) { if (tab_widget) {
QString qvn = PI2QString(vn); QString qvn = PI2QString(vn);
@@ -305,9 +322,10 @@ void PIValueTreeEdit::actionTriggered(QToolButton * button, const PIString & vn,
tree_edits.remove(vn); tree_edits.remove(vn);
comm_labels.remove(vn); comm_labels.remove(vn);
label_labels.remove(vn); label_labels.remove(vn);
return;
} }
if (a == widget_params->actionChange) {
void PIValueTreeEdit::actionChange(QToolButton * button, const PIString & vn) {
auto & vt(current[vn]); auto & vt(current[vn]);
if (vt.isArray()) { if (vt.isArray()) {
auto * ve = tree_edits.value(vn, nullptr); auto * ve = tree_edits.value(vn, nullptr);
@@ -349,9 +367,10 @@ void PIValueTreeEdit::actionTriggered(QToolButton * button, const PIString & vn,
} }
auto * cl = comm_labels.value(vn, nullptr); auto * cl = comm_labels.value(vn, nullptr);
if (cl) cl->setText(PIVariantEditorBase::vtTr(vt.comment())); if (cl) cl->setText(PIVariantEditorBase::vtTr(vt.comment()));
return;
} }
if (a == widget_params->actionReorder) {
void PIValueTreeEdit::actionReorder(QToolButton *, const PIString & vn) {
if (!widget_reorder->showFor(current)) return; if (!widget_reorder->showFor(current)) return;
grid->reorder(widget_reorder->map); grid->reorder(widget_reorder->map);
auto cl = current.children(); auto cl = current.children();
@@ -361,12 +380,86 @@ void PIValueTreeEdit::actionTriggered(QToolButton * button, const PIString & vn,
if (mi < 0 || mi >= cl.size_s()) continue; if (mi < 0 || mi >= cl.size_s()) continue;
current.addChild(cl[mi]); current.addChild(cl[mi]);
} }
}
void PIValueTreeEdit::actionCopy(QToolButton *, const PIString & vn) {
PIValueTree cur_val = value();
auto & vt(cur_val[vn]);
// piCout << vt;
PIString json =
PIValueTreeConversions::toJSON(vt, PIValueTreeConversions::Default | PIValueTreeConversions::IncludeRoot).toJSON(PIJSON::Tree);
QApplication::clipboard()->setText(PI2QString(json));
}
void PIValueTreeEdit::actionPaste(QToolButton * button, const PIString & vn, int offset) {
PIString json = Q2PIString(QApplication::clipboard()->text());
if (json.isEmpty()) return;
PIValueTree ins_val = PIValueTreeConversions::fromJSON(PIJSON::fromJSON(json));
// if (ins_val.name.isEmpty()) return;
PIValueTree cur_val = value();
cur_val.insertChild(cur_val.childIndex(vn) + offset, ins_val);
setValue(cur_val);
}
void PIValueTreeEdit::actionTriggered(QToolButton * button, const PIString & vn, QAction * a) {
if (a == widget_params->actionRename) {
actionRename(button, vn);
return;
}
if (a == widget_params->actionRemove) {
actionRemove(button, vn);
return;
}
if (a == widget_params->actionChange) {
actionChange(button, vn);
return;
}
if (a == widget_params->actionReorder) {
actionReorder(button, vn);
return;
}
if (a == widget_params->actionCut) {
actionCopy(button, vn);
actionRemove(button, vn);
return;
}
if (a == widget_params->actionCopy) {
actionCopy(button, vn);
return;
}
if (a == widget_params->actionPasteBefore) {
actionPaste(button, vn, 0);
return;
}
if (a == widget_params->actionPasteAfter) {
actionPaste(button, vn, 1);
return; return;
} }
setGrouping((Grouping)a->data().toInt()); setGrouping((Grouping)a->data().toInt());
} }
void PIValueTreeEdit::checkActions() {
bool can_paste = true;
PIString str = Q2PIString(QApplication::clipboard()->text());
if (str.isEmpty() || !str.startsWith("{")) {
can_paste = false;
} else {
PIJSON j = PIJSON::fromJSON(str);
if (!j.contains("name"))
can_paste = false;
else {
if (current.contains(j["name"].value().toString())) can_paste = false;
}
}
widget_params->actionPasteBefore->setEnabled(can_paste);
widget_params->actionPasteAfter->setEnabled(can_paste);
}
PIValueTreeEdit * PIValueTreeEdit::addTreeEdit(const PIValueTree & vt) { PIValueTreeEdit * PIValueTreeEdit::addTreeEdit(const PIValueTree & vt) {
auto * ve = new PIValueTreeEdit(); auto * ve = new PIValueTreeEdit();
PIStringList rp = root_path; PIStringList rp = root_path;
@@ -528,24 +621,21 @@ PIValueTreeEdit::GridWidgets::GridWidgets(PIValueTreeEdit * p) {
a->setSeparator(true); a->setSeparator(true);
return a; return a;
}; };
menu_group.addActions({p->widget_params->actionRename, auto * wp = p->widget_params;
p->widget_params->actionReorder, auto common_actions =
p->widget_params->menu_grouping.menuAction(), {newSeparator(), wp->actionCut, wp->actionCopy, wp->actionPasteBefore, wp->actionPasteAfter, newSeparator(), wp->actionRemove};
newSeparator(), menu_group.addActions({wp->actionRename, wp->actionReorder, wp->menu_grouping.menuAction()});
p->widget_params->actionRemove}); menu_conf.addActions({wp->actionRename, wp->actionChange, wp->actionReorder});
menu_conf.addActions({p->widget_params->actionRename, menu_group.addActions(common_actions);
p->widget_params->actionChange, menu_conf.addActions(common_actions);
p->widget_params->actionReorder, menu_new.addActions({wp->actionValue, wp->actionGroup, wp->actionArray});
newSeparator(),
p->widget_params->actionRemove});
menu_new.addActions({p->widget_params->actionValue, p->widget_params->actionGroup, p->widget_params->actionArray});
button_add = new QToolButton(); button_add = new QToolButton();
button_add->setIcon(QIcon(":/icons/list-add.png")); button_add->setIcon(QIcon(":/icons/list-add.png"));
button_add->setPopupMode(QToolButton::InstantPopup); button_add->setPopupMode(QToolButton::InstantPopup);
button_add->setMenu(&menu_new); button_add->setMenu(&menu_new);
p->widget_params->actionValue->setData((int)NewType::Value); wp->actionValue->setData((int)NewType::Value);
p->widget_params->actionGroup->setData((int)NewType::Group); wp->actionGroup->setData((int)NewType::Group);
p->widget_params->actionArray->setData((int)NewType::Array); wp->actionArray->setData((int)NewType::Array);
connect(button_add, &QToolButton::triggered, this, [this](QAction * a) { parent->newRequest((NewType)a->data().toInt()); }); connect(button_add, &QToolButton::triggered, this, [this](QAction * a) { parent->newRequest((NewType)a->data().toInt()); });
} }
@@ -612,12 +702,14 @@ void PIValueTreeEdit::GridWidgets::addRow(QWidget * w) {
QToolButton * PIValueTreeEdit::GridWidgets::createConfigButton(const PIValueTree & vt, bool is_group) { QToolButton * PIValueTreeEdit::GridWidgets::createConfigButton(const PIValueTree & vt, bool is_group) {
auto * b = new QToolButton(); auto * b = new ToolButton();
b->setIcon(icon_conf); b->setIcon(icon_conf);
b->setPopupMode(QToolButton::InstantPopup); b->setPopupMode(QToolButton::InstantPopup);
b->setMenu((is_group && !vt.isArray()) ? &menu_group : &menu_conf); b->setMenu((is_group && !vt.isArray()) ? &menu_group : &menu_conf);
b->setProperty(property_name, PI2QString(vt.name())); b->setProperty(property_name, PI2QString(vt.name()));
b->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); b->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
b->setPressHandler([this]() { parent->checkActions(); });
// connect(b, &QToolButton::pressed, parent, &PIValueTreeEdit::checkActions);
connect(b, &QToolButton::triggered, this, [this, b](QAction * a) { connect(b, &QToolButton::triggered, this, [this, b](QAction * a) {
parent->actionTriggered(b, Q2PIString(b->property(property_name).toString()), a); parent->actionTriggered(b, Q2PIString(b->property(property_name).toString()), a);
}); });

View File

@@ -80,7 +80,14 @@ private:
void removeAll(); void removeAll();
void build(); void build();
void applyValues() const; void applyValues() const;
void actionRename(QToolButton * button, const PIString & vn);
void actionRemove(QToolButton * button, const PIString & vn);
void actionChange(QToolButton * button, const PIString & vn);
void actionReorder(QToolButton * button, const PIString & vn);
void actionCopy(QToolButton * button, const PIString & vn);
void actionPaste(QToolButton * button, const PIString & vn, int offset);
void actionTriggered(QToolButton * button, const PIString & vn, QAction * a); void actionTriggered(QToolButton * button, const PIString & vn, QAction * a);
void checkActions();
void newRequest(NewType type); void newRequest(NewType type);
PIValueTreeEdit * addTreeEdit(const PIValueTree & vt); PIValueTreeEdit * addTreeEdit(const PIValueTree & vt);
PIValueTreeEdit * rootTreeEdit(); PIValueTreeEdit * rootTreeEdit();

View File

@@ -167,6 +167,48 @@
<string>Reorder ...</string> <string>Reorder ...</string>
</property> </property>
</action> </action>
<action name="actionCopy">
<property name="icon">
<iconset resource="../application/qad_application.qrc">
<normaloff>:/icons/edit-copy.png</normaloff>:/icons/edit-copy.png</iconset>
</property>
<property name="text">
<string>Copy</string>
</property>
</action>
<action name="actionCut">
<property name="icon">
<iconset resource="qad_piqt_widgets.qrc">
<normaloff>:/icons/edit-cut.png</normaloff>:/icons/edit-cut.png</iconset>
</property>
<property name="text">
<string>Cut</string>
</property>
</action>
<action name="actionPasteBefore">
<property name="icon">
<iconset resource="../utils/qad_utils.qrc">
<normaloff>:/icons/edit-paste.png</normaloff>:/icons/edit-paste.png</iconset>
</property>
<property name="text">
<string>Paste before</string>
</property>
<property name="toolTip">
<string>Paste before</string>
</property>
</action>
<action name="actionPasteAfter">
<property name="icon">
<iconset resource="../utils/qad_utils.qrc">
<normaloff>:/icons/edit-paste.png</normaloff>:/icons/edit-paste.png</iconset>
</property>
<property name="text">
<string>Paste after</string>
</property>
<property name="toolTip">
<string>Paste after</string>
</property>
</action>
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget> <customwidget>
@@ -185,6 +227,7 @@
<include location="../blockview/qad_blockview.qrc"/> <include location="../blockview/qad_blockview.qrc"/>
<include location="../graphic/qad_graphic.qrc"/> <include location="../graphic/qad_graphic.qrc"/>
<include location="qad_piqt_widgets.qrc"/> <include location="qad_piqt_widgets.qrc"/>
<include location="../utils/qad_utils.qrc"/>
</resources> </resources>
<connections> <connections>
<connection> <connection>

View File

@@ -45,76 +45,8 @@
</widget> </widget>
</item> </item>
</layout> </layout>
<action name="actionRemove">
<property name="icon">
<iconset resource="../blockview/qad_blockview.qrc">
<normaloff>:/icons/edit-delete.png</normaloff>:/icons/edit-delete.png</iconset>
</property>
<property name="text">
<string>Remove</string>
</property>
</action>
<action name="actionChange">
<property name="icon">
<iconset resource="../application/qad_application.qrc">
<normaloff>:/icons/configure.png</normaloff>:/icons/configure.png</iconset>
</property>
<property name="text">
<string>Change ...</string>
</property>
</action>
<action name="actionRename">
<property name="icon">
<iconset resource="../graphic/qad_graphic.qrc">
<normaloff>:/icons/border-line.png</normaloff>:/icons/border-line.png</iconset>
</property>
<property name="text">
<string>Rename ...</string>
</property>
</action>
<action name="actionValue">
<property name="icon">
<iconset resource="qad_piqt_widgets.qrc">
<normaloff>:/icons/code-variable.png</normaloff>:/icons/code-variable.png</iconset>
</property>
<property name="text">
<string>Value</string>
</property>
</action>
<action name="actionGroup">
<property name="icon">
<iconset resource="qad_piqt_widgets.qrc">
<normaloff>:/icons/code-struct.png</normaloff>:/icons/code-struct.png</iconset>
</property>
<property name="text">
<string>Group</string>
</property>
</action>
<action name="actionArray">
<property name="icon">
<iconset resource="qad_piqt_widgets.qrc">
<normaloff>:/icons/code-union.png</normaloff>:/icons/code-union.png</iconset>
</property>
<property name="text">
<string>Array</string>
</property>
</action>
<action name="actionReorder">
<property name="icon">
<iconset resource="../graphic/qad_graphic.qrc">
<normaloff>:/icons/legend.png</normaloff>:/icons/legend.png</iconset>
</property>
<property name="text">
<string>Reorder ...</string>
</property>
</action>
</widget> </widget>
<resources> <resources/>
<include location="../application/qad_application.qrc"/>
<include location="../blockview/qad_blockview.qrc"/>
<include location="../graphic/qad_graphic.qrc"/>
<include location="qad_piqt_widgets.qrc"/>
</resources>
<connections> <connections>
<connection> <connection>
<sender>buttonBox</sender> <sender>buttonBox</sender>

View File

@@ -74,6 +74,12 @@
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer> </spacer>
</item> </item>
</layout> </layout>
@@ -116,74 +122,10 @@
</widget> </widget>
</item> </item>
</layout> </layout>
<action name="actionRemove">
<property name="icon">
<iconset resource="../blockview/qad_blockview.qrc">
<normaloff>:/icons/edit-delete.png</normaloff>:/icons/edit-delete.png</iconset>
</property>
<property name="text">
<string>Remove</string>
</property>
</action>
<action name="actionChange">
<property name="icon">
<iconset resource="../application/qad_application.qrc">
<normaloff>:/icons/configure.png</normaloff>:/icons/configure.png</iconset>
</property>
<property name="text">
<string>Change ...</string>
</property>
</action>
<action name="actionRename">
<property name="icon">
<iconset resource="../graphic/qad_graphic.qrc">
<normaloff>:/icons/border-line.png</normaloff>:/icons/border-line.png</iconset>
</property>
<property name="text">
<string>Rename ...</string>
</property>
</action>
<action name="actionValue">
<property name="icon">
<iconset resource="qad_piqt_widgets.qrc">
<normaloff>:/icons/code-variable.png</normaloff>:/icons/code-variable.png</iconset>
</property>
<property name="text">
<string>Value</string>
</property>
</action>
<action name="actionGroup">
<property name="icon">
<iconset resource="qad_piqt_widgets.qrc">
<normaloff>:/icons/code-struct.png</normaloff>:/icons/code-struct.png</iconset>
</property>
<property name="text">
<string>Group</string>
</property>
</action>
<action name="actionArray">
<property name="icon">
<iconset resource="qad_piqt_widgets.qrc">
<normaloff>:/icons/code-union.png</normaloff>:/icons/code-union.png</iconset>
</property>
<property name="text">
<string>Array</string>
</property>
</action>
<action name="actionReorder">
<property name="icon">
<iconset resource="../graphic/qad_graphic.qrc">
<normaloff>:/icons/legend.png</normaloff>:/icons/legend.png</iconset>
</property>
<property name="text">
<string>Reorder ...</string>
</property>
</action>
</widget> </widget>
<resources> <resources>
<include location="../application/qad_application.qrc"/> <include location="../application/qad_application.qrc"/>
<include location="../blockview/qad_blockview.qrc"/> <include location="../blockview/qad_blockview.qrc"/>
<include location="../graphic/qad_graphic.qrc"/>
<include location="qad_piqt_widgets.qrc"/> <include location="qad_piqt_widgets.qrc"/>
</resources> </resources>
<connections> <connections>

View File

@@ -1,5 +1,6 @@
<RCC> <RCC>
<qresource prefix="/"> <qresource prefix="/">
<file>../../icons/edit-cut.png</file>
<file>../../icons/configure.png</file> <file>../../icons/configure.png</file>
<file>../../icons/border-line.png</file> <file>../../icons/border-line.png</file>
<file>../../icons/list-add.png</file> <file>../../icons/list-add.png</file>

View File

@@ -4,6 +4,7 @@
#include <QDebug> #include <QDebug>
#include <QDir> #include <QDir>
#include <QDirIterator> #include <QDirIterator>
#include <QLibraryInfo>
#include <QTranslator> #include <QTranslator>
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
# include <QStandardPaths> # include <QStandardPaths>
@@ -74,12 +75,22 @@ void QAD::loadTranslations(QString lang) {
if (lang.isEmpty()) lang = QLocale().bcp47Name(); if (lang.isEmpty()) lang = QLocale().bcp47Name();
QString short_lang = lang.left(2); QString short_lang = lang.left(2);
QStringList dirs = resourcePaths("lang"); QStringList dirs = resourcePaths("lang");
QString std_dir = QDir::cleanPath(QLibraryInfo::location(QLibraryInfo::TranslationsPath));
bool has_std = false;
for (const QString & d: dirs) {
if (QDir::cleanPath(d) == std_dir) {
has_std = true;
break;
}
}
if (!has_std) dirs << std_dir;
for (const QString & d: dirs) { for (const QString & d: dirs) {
QDirIterator dit(d); QDirIterator dit(d);
while (dit.hasNext()) { while (dit.hasNext()) {
dit.next(); dit.next();
if (!dit.filePath().endsWith(".qm")) continue; if (!dit.filePath().endsWith(".qm")) continue;
if (!dit.fileInfo().baseName().endsWith(lang) && !dit.fileInfo().baseName().endsWith(short_lang)) continue; if (!dit.fileInfo().baseName().endsWith(lang) && !dit.fileInfo().baseName().endsWith(short_lang)) continue;
if (dit.fileName() == QString("qt_%1.qm").arg(short_lang)) continue;
QTranslator * tr = new QTranslator(); QTranslator * tr = new QTranslator();
if (tr->load(dit.filePath())) { if (tr->load(dit.filePath())) {
qApp->installTranslator(tr); qApp->installTranslator(tr);