View Issue Details
| ID | Project | Category | View Status | Date Submitted | Last Update |
|---|---|---|---|---|---|
| 0017954 | Scribus | Guides | public | 2026-08-29 13:58 | 2026-08-29 13:59 |
| Reporter | qirat | Assigned To | |||
| Priority | normal | Severity | minor | Reproducibility | always |
| Status | new | Resolution | open | ||
| Platform | Linux | OS | Fedora Workstation | OS Version | 44 |
| Product Version | 1.7.4.svn | ||||
| Summary | 0017954: [patch] Fix Master Guide State Across Modes | ||||
| Description | #Follow-up * This patch is a follow-up to the `master-page-guides-inheritance-v1.3.patch` (0015624) and is intended to be applied on top of that patch/base. * It relies on the separate inherited-guide storage introduced there (`m_horizontalMasterG` / `m_verticalMasterG`). #Issue * After switching between normal and Master Page mode, Guide Manager could keep showing rows from the previously active page. * Those stale rows could remain editable, so edits/deletes could target the wrong page/master until the palette was refreshed by another interaction. * Inherited master guides shown on normal pages had no ownership indication and could appear to behave like ordinary local guides. * Local and inherited guides at the same coordinate could be represented as a single row, losing their separate ownership. #Cause * `GuideManager` could keep a stale `currentPage` across Master Page mode transitions. * The model treated guide position as identity, so a local guide and inherited master guide at the same coordinate were conflated. #Fix * Rebind the palette with `setupPage(false)` when entering/leaving Master Page mode. * Expose inherited guide lists separately through `GuideManagerCore`. * Track read-only state per `GuidesModel` row rather than by coordinate. * Keep coincident local/master guides as separate rows. * `setData()` / `flags()` reject editing inherited rows; removal paths skip them. * Add a tooltip identifying inherited rows and directing edits to Master Page mode. #Result * Inherited master guides are visible but read-only on normal pages. * Local guides remain editable/deletable. * Master guides are editable normally in Master Page mode. * Coincident local/master guides preserve correct ownership. * Guide Manager no longer retains stale guide data across mode switches. | ||||
| Tags | #please_test | ||||
| Attached Files | master-page-guides2-guide-manager-readonly-v1.1.patch (11,463 bytes)
Index: scribus/guidemanagercore.h
===================================================================
--- scribus/guidemanagercore.h (after master-page-guides-inheritance-v1.3)
+++ scribus/guidemanagercore.h (working copy)
@@ -56,6 +56,8 @@
Guides verticals(GuideType type) const;
Guides horizontalsWithMaster() const;
Guides verticalsWithMaster() const;
+ Guides masterPageHorizontals() const;
+ Guides masterPageVerticals() const;
double horizontal(uint ix, GuideType type) const;
double vertical(uint ix, GuideType type) const;
Index: scribus/guidemanagercore.cpp
===================================================================
--- scribus/guidemanagercore.cpp (after master-page-guides-inheritance-v1.3)
+++ scribus/guidemanagercore.cpp (working copy)
@@ -213,6 +213,16 @@
guides.append(guidePos);
}
return guides;
+}
+
+Guides GuideManagerCore::masterPageHorizontals() const
+{
+ return m_horizontalMasterG;
+}
+
+Guides GuideManagerCore::masterPageVerticals() const
+{
+ return m_verticalMasterG;
}
double GuideManagerCore::horizontal(uint ix, GuideType type) const
Index: scribus/guidesmodel.h
===================================================================
--- scribus/guidesmodel.h (after master-page-guides-inheritance-v1.3)
+++ scribus/guidesmodel.h (working copy)
@@ -12,8 +12,7 @@
/*! \brief A model for guides lists.
-It holds guides as a double QList (it will be expanded later because of RFEs)
-and it handles its values editing too. The editor from GuidesDelegate
+It holds guide values and per-row state, and handles value editing too. The editor from GuidesDelegate
is used.
See Qt4 documentation for more info about its methods.
FIXME: unit conversions for dipslay vs. internal
@@ -37,17 +36,18 @@
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
- void removeValues(const Guides & guides);
- // qt4 api is "wrokarounded" with insertRow() and removeValues()
+ bool removeIndexes(const QModelIndexList& indexes);
+ // qt4 api is "wrokarounded" with insertRow() and removeIndexes()
// these removeRows() and insertRows() does not handle margin items correctly
// bool removeRows(int row, int count, const QModelIndex & parent = QModelIndex());
// bool insertRows( int row, int count, const QModelIndex & parent = QModelIndex());
void insertRow();
//! \brief Set new values into the model.
- void setValues(const Guides& values);
+ void setValues(const Guides& editableValues, const Guides& readOnlyValues = Guides());
//! \brief Get values back to the app.
const Guides& values() const;
+ Guides editableValues() const;
void unitChange(int docUnitIndex, int docUnitDecimals, double offset);
#if 0
@@ -61,7 +61,10 @@
void valueChanged();
private:
+ void sortValues();
+
Guides m_values;
+ QList<bool> m_readOnlyRows;
int m_docUnitIndex {0};
int m_docUnitDecimals {0};
double m_rule {0.0};
Index: scribus/guidesmodel.cpp
===================================================================
--- scribus/guidesmodel.cpp (after master-page-guides-inheritance-v1.3)
+++ scribus/guidesmodel.cpp (working copy)
@@ -7,6 +7,7 @@
#include <algorithm>
#include <QLocale>
+#include <QPair>
#include "guidesmodel.h"
#include "units.h"
@@ -49,6 +50,8 @@
return pts2value(m_values.at(index.row()) - m_rule, m_docUnitIndex);
if (role == Qt::UserRole)
return m_values.at(index.row());
+ if (role == Qt::ToolTipRole && m_readOnlyRows.at(index.row()))
+ return tr("Inherited from master page. Edit this guide in Master Page mode.");
if (role == Qt::BackgroundRole && m_values.at(index.row()) == 0.0)
return QVariant(QColor(Qt::red));
@@ -57,22 +60,31 @@
bool GuidesModel::setData(const QModelIndex & index, const QVariant & value, int role)
{
- if (role != Qt::EditRole || !index.isValid())
+ if (role != Qt::EditRole || !index.isValid() || m_readOnlyRows.at(index.row()))
return false;
bool ok;
double newVal = value.toDouble(&ok);
if (!ok)
return false;
- m_values[index.row()] = value2pts(newVal, m_docUnitIndex) + m_rule;
- std::sort(m_values.begin(), m_values.end());
+ double newValue = value2pts(newVal, m_docUnitIndex) + m_rule;
+ for (int i = 0; i < m_values.count(); ++i)
+ {
+ if (m_readOnlyRows.at(i) && m_values.at(i) == newValue)
+ return false;
+ }
+ m_values[index.row()] = newValue;
+ sortValues();
emit dataChanged(index, index);
emit valueChanged();
return true;
}
-Qt::ItemFlags GuidesModel::flags(const QModelIndex & /*index*/) const
-{
- return Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable;
+Qt::ItemFlags GuidesModel::flags(const QModelIndex & index) const
+{
+ Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
+ if (index.isValid() && !m_readOnlyRows.at(index.row()))
+ flags |= Qt::ItemIsEditable;
+ return flags;
}
QVariant GuidesModel::headerData(int /*section*/, Qt::Orientation orientation, int /*role*/) const
@@ -82,12 +94,26 @@
return "";
}
-void GuidesModel::removeValues(const Guides & guides)
-{
- beginResetModel();
- for (double d : guides)
- m_values.removeAll(d);
- endResetModel();
+bool GuidesModel::removeIndexes(const QModelIndexList& indexes)
+{
+ QList<int> rows;
+ for (const QModelIndex& index : indexes)
+ {
+ if (index.isValid() && !m_readOnlyRows.at(index.row()) && !rows.contains(index.row()))
+ rows.append(index.row());
+ }
+ if (rows.isEmpty())
+ return false;
+
+ std::sort(rows.begin(), rows.end(), [](int a, int b) { return a > b; });
+ beginResetModel();
+ for (int row : rows)
+ {
+ m_values.removeAt(row);
+ m_readOnlyRows.removeAt(row);
+ }
+ endResetModel();
+ return true;
}
// bool GuidesModel::removeRows(int row, int count, const QModelIndex & parent)
@@ -114,25 +140,64 @@
void GuidesModel::insertRow()
{
// insertRows(rowCount(), 1);
- beginResetModel();
if (m_values.contains(0.0))
return;
+ beginResetModel();
m_values.append(0.0);
- std::sort(m_values.begin(), m_values.end());
- endResetModel();
-}
-
-void GuidesModel::setValues(const Guides& values)
-{
- beginResetModel();
- m_values = values;
- std::sort(m_values.begin(), m_values.end());
+ m_readOnlyRows.append(false);
+ sortValues();
+ endResetModel();
+}
+
+void GuidesModel::setValues(const Guides& editableValues, const Guides& readOnlyValues)
+{
+ beginResetModel();
+ m_values = editableValues;
+ m_readOnlyRows.clear();
+ for (int i = 0; i < editableValues.count(); ++i)
+ m_readOnlyRows.append(false);
+ for (double value : readOnlyValues)
+ {
+ m_values.append(value);
+ m_readOnlyRows.append(true);
+ }
+ sortValues();
endResetModel();
}
const Guides& GuidesModel::values() const
{
return m_values;
+}
+
+Guides GuidesModel::editableValues() const
+{
+ Guides values;
+ for (int i = 0; i < m_values.count(); ++i)
+ {
+ if (!m_readOnlyRows.at(i))
+ values.append(m_values.at(i));
+ }
+ return values;
+}
+
+void GuidesModel::sortValues()
+{
+ QList<QPair<double, bool>> entries;
+ for (int i = 0; i < m_values.count(); ++i)
+ entries.append(qMakePair(m_values.at(i), m_readOnlyRows.at(i)));
+
+ std::sort(entries.begin(), entries.end(), [](const QPair<double, bool>& a, const QPair<double, bool>& b)
+ {
+ if (a.first == b.first)
+ return a.second < b.second;
+ return a.first < b.first;
+ });
+ for (int i = 0; i < entries.count(); ++i)
+ {
+ m_values[i] = entries.at(i).first;
+ m_readOnlyRows[i] = entries.at(i).second;
+ }
}
void GuidesModel::unitChange(int docUnitIndex, int docUnitDecimals,double offset)
Index: scribus/ui/guidemanager.cpp
===================================================================
--- scribus/ui/guidemanager.cpp (after master-page-guides-inheritance-v1.3)
+++ scribus/ui/guidemanager.cpp (working copy)
@@ -267,36 +267,24 @@
void GuideManager::delHorButton_clicked()
{
const QModelIndexList indexes = horizontalView->selectionModel()->selectedRows(0);
- Guides v;
-
- for (const QModelIndex& ix : indexes)
- // here *must* go EditRole due truncations in DisplayRole
- // see GuidesModel::data()
- v.append(horizontalModel->data(ix, Qt::UserRole).toDouble());
-
- horizontalModel->removeValues(v);
+ if (!horizontalModel->removeIndexes(indexes))
+ return;
currentPage->guides.clearHorizontals(GuideManagerCore::Standard);
- currentPage->guides.addHorizontals(horizontalModel->values(), GuideManagerCore::Standard);
- drawGuides();
+ currentPage->guides.addHorizontals(horizontalModel->editableValues(), GuideManagerCore::Standard);
+ clearRestoreHorizontalList();
m_doc->changed();
}
void GuideManager::delVerButton_clicked()
{
const QModelIndexList indexes = verticalView->selectionModel()->selectedRows(0);
- Guides v;
-
- for (const QModelIndex& ix : indexes)
- // here *must* go EditRole due truncations in DisplayRole
- // see GuidesModel::data()
- v.append(verticalModel->data(ix, Qt::UserRole).toDouble());
-
- verticalModel->removeValues(v);
+ if (!verticalModel->removeIndexes(indexes))
+ return;
currentPage->guides.clearVerticals(GuideManagerCore::Standard);
- currentPage->guides.addVerticals(verticalModel->values(), GuideManagerCore::Standard);
- drawGuides();
+ currentPage->guides.addVerticals(verticalModel->editableValues(), GuideManagerCore::Standard);
+ clearRestoreVerticalList();
m_doc->changed();
}
@@ -474,13 +462,15 @@
void GuideManager::clearRestoreHorizontalList()
{
- horizontalModel->setValues(currentPage->guides.horizontals(GuideManagerCore::Standard));
+ horizontalModel->setValues(currentPage->guides.horizontals(GuideManagerCore::Standard),
+ currentPage->guides.masterPageHorizontals());
drawGuides();
}
void GuideManager::clearRestoreVerticalList()
{
- verticalModel->setValues(currentPage->guides.verticals(GuideManagerCore::Standard));
+ verticalModel->setValues(currentPage->guides.verticals(GuideManagerCore::Standard),
+ currentPage->guides.masterPageVerticals());
drawGuides();
}
@@ -595,16 +585,16 @@
void GuideManager::verticalModel_valueChanged()
{
currentPage->guides.clearVerticals(GuideManagerCore::Standard);
- currentPage->guides.addVerticals(verticalModel->values(), GuideManagerCore::Standard);
- drawGuides();
+ currentPage->guides.addVerticals(verticalModel->editableValues(), GuideManagerCore::Standard);
+ clearRestoreVerticalList();
m_doc->changed();
}
void GuideManager::horizontalModel_valueChanged()
{
currentPage->guides.clearHorizontals(GuideManagerCore::Standard);
- currentPage->guides.addHorizontals(horizontalModel->values(), GuideManagerCore::Standard);
- drawGuides();
+ currentPage->guides.addHorizontals(horizontalModel->editableValues(), GuideManagerCore::Standard);
+ clearRestoreHorizontalList();
m_doc->changed();
}
Index: scribus/scribus.cpp
===================================================================
--- scribus/scribus.cpp (after master-page-guides-inheritance-v1.3)
+++ scribus/scribus.cpp (working copy)
@@ -7728,12 +7728,14 @@
if (doc->masterPageMode())
{
pagePalette->startMasterPageMode(mpName);
+ guidePalette->setupPage(false);
return;
}
view->saveViewState();
pagePalette->startMasterPageMode(mpName);
+ guidePalette->setupPage(false);
if (pagePalette->isClosed())
{
auto* area = pagePalette->dockAreaWidget();
@@ -7770,6 +7772,7 @@
view->reformPages(false);
view->setContentsPos(viewState.contentX, viewState.contentY);
doc->setLoading(false);
+ guidePalette->setupPage(false);
view->DrawNew();
}
| ||||
| Patch | Yes | ||||