mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-08-03 18:44:13 +02:00
bb61dde811
ElementsPanel and ElementsTreeView already force a fixed light palette (white base, black text) on themselves, specifically because element icons are rendered with colors read directly from each .elmt file -- almost always black linework, matching printed-schematic convention -- onto a transparent background. That only stays legible if the row background is reliably light, regardless of the OS/desktop theme. But QAbstractItemView paints row backgrounds using its viewport's palette, not the view widget's own palette. setPalette() on the view itself doesn't propagate to viewport() in the general case, so under styles that actually respect the viewport's (unset, therefore theme-inherited) palette -- e.g. KDE Plasma's Breeze Dark -- the row background falls through to the app's dark palette while the element linework is still literal black, making library icons and terminal symbols invisible. Apply the same QPalette to viewport() right after setPalette() in both constructors, so the fix these two classes already clearly intended actually takes effect under every style. Fixes https://qelectrotech.org/bugtracker/view.php?id=335
255 lines
8.7 KiB
C++
255 lines
8.7 KiB
C++
/*
|
|
Copyright 2006-2026 The QElectroTech Team
|
|
This file is part of QElectroTech.
|
|
|
|
QElectroTech is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
QElectroTech 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 General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
#include "elementstreeview.h"
|
|
|
|
#include "../factory/elementfactory.h"
|
|
#include "../qetgraphicsitem/element.h"
|
|
#include "../qeticons.h"
|
|
#include "elementcollectionitem.h"
|
|
#include "elementslocation.h"
|
|
#include "../qetproject.h"
|
|
#include "../diagram.h"
|
|
#include "xmlelementcollection.h"
|
|
#include "../NameList/nameslist.h"
|
|
#include <QPainter>
|
|
#include <QScopedPointer>
|
|
#include <QDrag>
|
|
#include <QStandardItemModel>
|
|
|
|
static int MAX_DND_PIXMAP_WIDTH = 500;
|
|
static int MAX_DND_PIXMAP_HEIGHT = 375;
|
|
|
|
/**
|
|
@brief ElementsTreeView::ElementsTreeView
|
|
@param parent
|
|
*/
|
|
ElementsTreeView::ElementsTreeView(QWidget *parent) :
|
|
QTreeView(parent)
|
|
{
|
|
// force du noir sur une alternance de blanc (comme le schema) et de gris
|
|
// clair, avec du blanc sur bleu pas trop fonce pour la selection
|
|
//
|
|
// Element icons are rendered with colors read directly from each .elmt
|
|
// file (almost always black linework, matching printed-schematic
|
|
// convention) onto a transparent background -- so this view must keep
|
|
// a light background regardless of the OS/desktop theme, or the icons
|
|
// become invisible on dark themes. QAbstractItemView paints its rows
|
|
// using the viewport's palette, not the view's own, so the palette
|
|
// must be applied to both to actually take effect under every style.
|
|
QPalette qp = palette();
|
|
qp.setColor(QPalette::Text, Qt::black);
|
|
qp.setColor(QPalette::Base, Qt::white);
|
|
qp.setColor(QPalette::AlternateBase, QColor("#e8e8e8"));
|
|
qp.setColor(QPalette::Highlight, QColor("#678db2"));
|
|
qp.setColor(QPalette::HighlightedText, Qt::black);
|
|
setPalette(qp);
|
|
viewport()->setPalette(qp);
|
|
}
|
|
|
|
/**
|
|
@brief ElementsTreeView::startDrag
|
|
Reimplemented from QTreeView
|
|
@param supportedActions
|
|
*/
|
|
void ElementsTreeView::startDrag(Qt::DropActions supportedActions)
|
|
{
|
|
QModelIndex index = currentIndex();
|
|
|
|
if (!index.isValid()) {
|
|
QTreeView::startDrag(supportedActions);
|
|
return;
|
|
}
|
|
|
|
if (QStandardItemModel *qsim = static_cast<QStandardItemModel *>(model())) {
|
|
if (ElementCollectionItem *eci = static_cast<ElementCollectionItem *>(qsim->itemFromIndex(index))) {
|
|
ElementsLocation loc (eci->collectionPath());
|
|
if (loc.exist()) {
|
|
startElementDrag(loc);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
QTreeView::startDrag(supportedActions);
|
|
}
|
|
|
|
/**
|
|
@brief ElementsTreeView::startElementDrag
|
|
Build a QDrag according to the content of location
|
|
@param location : location to use for create the content of the QDrag
|
|
*/
|
|
void ElementsTreeView::startElementDrag(const ElementsLocation &location)
|
|
{
|
|
if (! location.exist()) return;
|
|
|
|
#if QT_VERSION < QT_VERSION_CHECK(6, 2, 0)
|
|
QDrag* drag = new QDrag(this);
|
|
#else
|
|
QScopedPointer<QDrag> drag(new QDrag(this));
|
|
#endif
|
|
|
|
QString location_str = location.toString();
|
|
QMimeData *mime_data = new QMimeData();
|
|
mime_data->setText(location_str);
|
|
|
|
if (location.isDirectory())
|
|
{
|
|
mime_data->setData("application/x-qet-category-uri",
|
|
location_str.toLatin1());
|
|
drag->setPixmap(QET::Icons::Folder.pixmap(22, 22));
|
|
}
|
|
else if (location.fileName().endsWith(".qetmak"))
|
|
{
|
|
mime_data->setData("application/x-qet-element-uri", location_str.toLatin1());
|
|
|
|
QPixmap macro_pixmap;
|
|
|
|
// --- MINI-RENDERER FÜR DAS MAKRO-VORSCHAUBILD ---
|
|
QFile file(location.fileSystemPath());
|
|
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
|
QDomDocument macro_doc;
|
|
if (macro_doc.setContent(&file)) {
|
|
QDomElement root = macro_doc.documentElement();
|
|
if (root.tagName() == "qet_macro") {
|
|
|
|
// 1. Unsichtbares Dummy-Projekt erstellen
|
|
QScopedPointer<QETProject> dummy_project(new QETProject());
|
|
|
|
// 2. Bauteile in das Dummy-Projekt laden (wie beim echten Drop)
|
|
QDomElement collection_node = root.firstChildElement("collection");
|
|
if (!collection_node.isNull()) {
|
|
QDomNodeList elements = collection_node.elementsByTagName("element");
|
|
for (int i = 0; i < elements.count(); ++i) {
|
|
QDomElement elmt_node = elements.at(i).toElement();
|
|
QString path = elmt_node.attribute("path");
|
|
QDomElement definition = elmt_node.firstChildElement("definition");
|
|
if (!path.isEmpty() && !definition.isNull()) {
|
|
int last_slash = path.lastIndexOf('/');
|
|
QString dir_path = (last_slash != -1) ? path.left(last_slash) : "";
|
|
QString file_name = (last_slash != -1) ? path.mid(last_slash + 1) : path;
|
|
|
|
if (!dir_path.isEmpty()) {
|
|
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
|
|
QStringList parts = dir_path.split('/', QString::SkipEmptyParts);
|
|
#else
|
|
QStringList parts = dir_path.split('/', Qt::SkipEmptyParts);
|
|
#endif
|
|
QString current_path = "";
|
|
for (const QString &part : parts) {
|
|
QString parent_path = current_path;
|
|
if (!current_path.isEmpty()) current_path += "/";
|
|
current_path += part;
|
|
if (current_path == "import") continue;
|
|
NamesList empty_names;
|
|
dummy_project->embeddedElementCollection()->createDir(parent_path, part, empty_names);
|
|
}
|
|
}
|
|
dummy_project->embeddedElementCollection()->addElementDefinition(dir_path, file_name, definition);
|
|
}
|
|
}
|
|
}
|
|
|
|
Diagram *dummy_diagram = dummy_project->addNewDiagram();
|
|
|
|
// 4. Makro auf dem unsichtbaren Blatt zeichnen
|
|
QDomElement diagram_content_node = root.firstChildElement("diagram_content");
|
|
QDomElement diagram_node = diagram_content_node.firstChildElement("diagram");
|
|
if (!diagram_node.isNull()) {
|
|
QDomNodeList instances = diagram_node.elementsByTagName("element");
|
|
for (int i = 0; i < instances.count(); ++i) {
|
|
QDomElement inst = instances.at(i).toElement();
|
|
QString type = inst.attribute("type");
|
|
if (type.startsWith("macro://")) {
|
|
inst.setAttribute("type", type.replace("macro://", "embed://"));
|
|
}
|
|
}
|
|
|
|
dummy_diagram->fromXml(diagram_node, QPointF(0, 0), false, nullptr);
|
|
dummy_diagram->clearSelection();
|
|
|
|
// 5. "Screenshot" (Pixmap) von den gezeichneten Elementen machen
|
|
QRectF scene_rect = dummy_diagram->itemsBoundingRect();
|
|
if (!scene_rect.isEmpty()) {
|
|
scene_rect.adjust(-5, -5, 5, 5); // Kleiner Rand
|
|
macro_pixmap = QPixmap(scene_rect.size().toSize());
|
|
macro_pixmap.fill(Qt::transparent); // Transparenter Hintergrund
|
|
|
|
QPainter painter(¯o_pixmap);
|
|
painter.setRenderHint(QPainter::Antialiasing);
|
|
dummy_diagram->render(&painter, macro_pixmap.rect(), scene_rect);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (macro_pixmap.isNull()) {
|
|
macro_pixmap = QET::Icons::Project.pixmap(32, 32);
|
|
}
|
|
|
|
// Bild verkleinern, falls das Makro gigantisch groß ist
|
|
if (macro_pixmap.width() > MAX_DND_PIXMAP_WIDTH || macro_pixmap.height() > MAX_DND_PIXMAP_HEIGHT) {
|
|
macro_pixmap = macro_pixmap.scaled(MAX_DND_PIXMAP_WIDTH, MAX_DND_PIXMAP_HEIGHT, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
|
}
|
|
|
|
drag->setPixmap(macro_pixmap);
|
|
// Bild zentriert an die Maus hängen
|
|
drag->setHotSpot(QPoint(macro_pixmap.width() / 2, macro_pixmap.height() / 2));
|
|
}
|
|
else if (location.isElement())
|
|
{
|
|
mime_data->setData("application/x-qet-element-uri",
|
|
location_str.toLatin1());
|
|
|
|
//Build the element for set the pixmap of the QDrag
|
|
int elmt_creation_state;
|
|
QScopedPointer<Element> temp_elmt(
|
|
ElementFactory::Instance()->createElement(
|
|
location,
|
|
nullptr,
|
|
&elmt_creation_state));
|
|
if (elmt_creation_state) { return; }
|
|
|
|
QPixmap elmt_pixmap(temp_elmt->pixmap());
|
|
QPoint elmt_hotspot(temp_elmt->hotspot());
|
|
|
|
//Adjust the size of the pixmap if he is too big
|
|
QPoint elmt_pixmap_size(elmt_pixmap.width(),
|
|
elmt_pixmap.height());
|
|
if (elmt_pixmap.width()
|
|
> MAX_DND_PIXMAP_WIDTH
|
|
|| elmt_pixmap.height()
|
|
> MAX_DND_PIXMAP_HEIGHT)
|
|
{
|
|
elmt_pixmap = elmt_pixmap.scaled(
|
|
MAX_DND_PIXMAP_WIDTH,
|
|
MAX_DND_PIXMAP_HEIGHT,
|
|
Qt::KeepAspectRatio);
|
|
elmt_hotspot = QPoint(
|
|
elmt_hotspot.x() * elmt_pixmap.width() / elmt_pixmap_size.x(),
|
|
elmt_hotspot.y() * elmt_pixmap.height() / elmt_pixmap_size.y()
|
|
);
|
|
}
|
|
|
|
drag->setPixmap(elmt_pixmap);
|
|
drag->setHotSpot(elmt_hotspot);
|
|
}
|
|
|
|
drag->setMimeData(mime_data);
|
|
drag->exec(Qt::CopyAction);
|
|
}
|