View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0011032 | Scribus | Story Editor / Text Frames | public | 2012-08-14 12:49 | 2012-11-13 20:23 |
Reporter | cezaryece | Assigned To | cbradney | ||
Priority | normal | Severity | feature | Reproducibility | N/A |
Status | closed | Resolution | fixed | ||
Product Version | 1.5.0svn | ||||
Fixed in Version | 1.5.0svn | ||||
Summary | 0011032: [PATCH] marks/footnotes feature | ||||
Description | In attachment you can find patch with marks/footnotes feature. Now marks/footnotes are handled by undo/redo and copy/paste operations. Basic footnotes import from ODT files is provided (only note mark position in text and note`s text in footnotes frame, as for now settings for footnotes from ODT file are not supported). We discus with Ale and agree that there is need for more testers and thus footnotes should be in trunk already. Diff file is from GIT and if for Craig it will be easier then footnotes branch can be pulled instead of attached patch. | ||||
Tags | No tags attached. | ||||
Patch | |||||
|
Any chance to commit this before end of August? |
|
Any chance of a commit? Footnotes have been tested by ale, jluc and pygmee. |
|
Where is this up to? Has it now been tested enough to commit? Please produce a new diff ready for commit. |
|
Ping |
|
footnotes.diff (375,082 bytes)
diff --git Scribus/Scribus.pro Scribus/Scribus.pro index a10ffc2..f9844bc 100644 --- Scribus/Scribus.pro +++ Scribus/Scribus.pro @@ -1112,7 +1112,18 @@ HEADERS += scribus/actionmanager.h \ scribus/plugins/scripter/api_printer.h \ scribus/plugins/scripter/api_layer.h \ scribus/plugins/scripter/api_imageitem.h \ - scribus/plugins/scripter/api_imageexport.h + scribus/plugins/scripter/api_imageexport.h \ + scribus/marks.h \ + scribus/notesstyles.h \ + scribus/pageitem_noteframe.h \ + scribus/ui/notesstyleseditor.h \ + scribus/ui/markvariabletext.h \ + scribus/ui/marksmanager.h \ + scribus/ui/marknote.h \ + scribus/ui/MarkInsertDlg.h \ + scribus/ui/markanchor.h \ + scribus/ui/mark2mark.h \ + scribus/ui/mark2item.h FORMS += scribus/ui/aboutplugins.ui \ scribus/ui/aligndistribute.ui \ scribus/ui/arcvectorbase.ui \ @@ -1240,7 +1251,14 @@ FORMS += scribus/ui/aboutplugins.ui \ scribus/plugins/tools/spellcheck/aspellpluginbase.ui \ scribus/plugins/scripter/python/sceditor/mainwindow.ui \ scribus/plugins/tools/2geomtools/meshdistortion/meshdistortiondialog.ui \ - scribus/plugins/tools/2geomtools/pathalongpath/pathdialogbase.ui + scribus/plugins/tools/2geomtools/pathalongpath/pathdialogbase.ui \ + scribus/ui/notesstyleseditor.ui \ + scribus/ui/markvariabletext.ui \ + scribus/ui/marksmanager.ui \ + scribus/ui/marknote.ui \ + scribus/ui/markanchor.ui \ + scribus/ui/mark2mark.ui \ + scribus/ui/mark2item.ui SOURCES += scribus/actionmanager.cpp \ scribus/canvas.cpp \ scribus/canvasgesture_cellselect.cpp \ @@ -2140,7 +2158,17 @@ SOURCES += scribus/actionmanager.cpp \ scribus/plugins/scripter/api_printer.cpp \ scribus/plugins/scripter/api_layer.cpp \ scribus/plugins/scripter/api_imageitem.cpp \ - scribus/plugins/scripter/api_imageexport.cpp + scribus/plugins/scripter/api_imageexport.cpp \ + scribus/notesstyles.cpp \ + scribus/pageitem_noteframe.cpp \ + scribus/ui/mark2item.cpp \ + scribus/ui/notesstyleseditor.cpp \ + scribus/ui/markvariabletext.cpp \ + scribus/ui/marksmanager.cpp \ + scribus/ui/marknote.cpp \ + scribus/ui/markanchor.cpp \ + scribus/ui/mark2mark.cpp \ + scribus/canvasmode_imageimport.cpp RESOURCES += scribus/plugins/scripter/python/sceditor/dockwidget_icons.qrc TRANSLATIONS += resources/translations/po/scribus.af.ts \ resources/translations/po/scribus.ar.ts \ diff --git Scribus/scribus/CMakeLists.txt Scribus/scribus/CMakeLists.txt index f7a9614..3bea07f 100644 --- Scribus/scribus/CMakeLists.txt +++ Scribus/scribus/CMakeLists.txt @@ -85,11 +85,18 @@ SET(SCRIBUS_UI_SRC ui/inserttablerowsdialog.ui ui/latexeditor.ui ui/newmarginwidgetbase.ui +ui/mark2item.ui +ui/mark2mark.ui +ui/markanchor.ui +ui/marknote.ui +ui/markvariabletext.ui +ui/marksmanager.ui ui/measurementsbase.ui ui/multipleduplicate.ui ui/multiprogressdialog.ui ui/nftdialog.ui ui/nftwidget.ui +ui/notesstyleseditor.ui ui/pageitemattributes.ui ui/pagepalette_pagesbase.ui ui/pagepalette_masterpagesbase.ui @@ -209,7 +216,9 @@ SET(SCRIBUS_MOC_CLASSES latexhelpers.h loadsaveplugin.h menumanager.h +marks.h navigator.h +notesstyles.h observable.h pageitem.h pageitem_arc.h @@ -225,6 +234,7 @@ SET(SCRIBUS_MOC_CLASSES pageitem_symbol.h pageitem_table.h pageitem_textframe.h +pageitem_noteframe.h pageitempointer.h pdf_analyzer.h pdflib.h @@ -316,6 +326,13 @@ SET(SCRIBUS_MOC_CLASSES ui/latexeditor.h ui/layers.h ui/loremipsum.h +ui/MarkInsertDlg.h +ui/mark2item.h +ui/mark2mark.h +ui/markanchor.h +ui/marknote.h +ui/markvariabletext.h +ui/marksmanager.h ui/margindialog.h ui/marginpresetlayout.h ui/marginwidget.h @@ -331,6 +348,7 @@ SET(SCRIBUS_MOC_CLASSES ui/nftdialog.h ui/nftwidget.h ui/nodeeditpalette.h +ui/notesstyleseditor.h ui/oneclick.h ui/outlinepalette.h ui/pageitemattributes.h @@ -563,6 +581,7 @@ SET(SCRIBUS_SOURCES nftrcreader.cpp nftsettings.cpp nfttemplate.cpp +notesstyles.cpp pageitem.cpp pageitem_arc.cpp pageitem_group.cpp @@ -577,6 +596,7 @@ SET(SCRIBUS_SOURCES pageitem_symbol.cpp pageitem_table.cpp pageitem_textframe.cpp +pageitem_noteframe.cpp pageitempointer.cpp pagesize.cpp pdf_analyzer.cpp @@ -748,6 +768,12 @@ SET(SCRIBUS_SOURCES ui/linecombo.cpp ui/linkbutton.cpp ui/loremipsum.cpp +ui/mark2item.cpp +ui/mark2mark.cpp +ui/markanchor.cpp +ui/marknote.cpp +ui/markvariabletext.cpp +ui/marksmanager.cpp ui/margindialog.cpp ui/marginpresetlayout.cpp ui/marginwidget.cpp @@ -763,6 +789,7 @@ SET(SCRIBUS_SOURCES ui/nftdialog.cpp ui/nftwidget.cpp ui/nodeeditpalette.cpp +ui/notesstyleseditor.cpp ui/oneclick.cpp ui/outlinepalette.cpp ui/pageitemattributes.cpp diff --git Scribus/scribus/actionmanager.cpp Scribus/scribus/actionmanager.cpp index 255adc6..1226a9c 100644 --- Scribus/scribus/actionmanager.cpp +++ Scribus/scribus/actionmanager.cpp @@ -240,8 +240,14 @@ void ActionManager::initEditMenuActions() scrActions->insert(name, new ScrAction("", defaultKey(name), mainWindow)); name="editJavascripts"; scrActions->insert(name, new ScrAction("", defaultKey(name), mainWindow)); + name="editMarks"; + scrActions->insert(name, new ScrAction("", defaultKey(name), mainWindow)); + name="editNotesStyles"; + scrActions->insert(name, new ScrAction("", defaultKey(name), mainWindow)); (*scrActions)["editStyles"]->setToggleAction(true); + (*scrActions)["editMarks"]->setToggleAction(true); + (*scrActions)["editNotesStyles"]->setToggleAction(true); connect( (*scrActions)["editUndoAction"], SIGNAL(triggeredData(int)) , undoManager, SLOT(undo(int)) ); connect( (*scrActions)["editRedoAction"], SIGNAL(triggeredData(int)) , undoManager, SLOT(redo(int)) ); @@ -542,10 +548,45 @@ void ActionManager::initInsertMenuActions() scrActions->insert(name, new ScrAction("", defaultKey(name), mainWindow)); (*scrActions)["stickyTools"]->setToggleAction(true); + //Marks + name="insertMarkAnchor"; + scrActions->insert(name, new ScrAction("", defaultKey(name), mainWindow)); + (*scrActions)[name]->setEnabled(true); + name="insertMarkVariableText"; + scrActions->insert(name, new ScrAction("", defaultKey(name), mainWindow)); + (*scrActions)[name]->setEnabled(true); + name="insertMarkItem"; + scrActions->insert(name, new ScrAction("", defaultKey(name), mainWindow)); + (*scrActions)[name]->setEnabled(true); + name="insertMark2Mark"; + scrActions->insert(name, new ScrAction("", defaultKey(name), mainWindow)); + (*scrActions)[name]->setEnabled(true); + name="insertMarkNote"; + scrActions->insert(name, new ScrAction("", defaultKey(name), mainWindow)); + (*scrActions)[name]->setEnabled(true); +// name="insertMarkIndex"; +// scrActions->insert(name, new ScrAction("", defaultKey(name), mainWindow)); +// (*scrActions)[name]->setEnabled(true); + name="editMark"; + scrActions->insert(name, new ScrAction("", defaultKey(name), mainWindow)); + (*scrActions)[name]->setEnabled(false); + name="itemUpdateMarks"; + scrActions->insert(name, new ScrAction("", defaultKey(name), mainWindow)); + (*scrActions)[name]->setEnabled(false); + connect( (*scrActions)["insertFrame"], SIGNAL(triggered()), mainWindow, SLOT(slotInsertFrame()) ); connect( (*scrActions)["insertGlyph"], SIGNAL(triggered()), mainWindow, SLOT(slotCharSelect()) ); connect( (*scrActions)["insertSampleText"], SIGNAL(triggered()), mainWindow, SLOT(insertSampleText()) ); connect( (*scrActions)["stickyTools"], SIGNAL(triggered()), mainWindow, SLOT(ToggleStickyTools()) ); + + connect( (*scrActions)["insertMarkAnchor"], SIGNAL(triggered()), mainWindow, SLOT(slotInsertMarkAnchor()) ); + connect( (*scrActions)["insertMarkVariableText"], SIGNAL(triggered()), mainWindow, SLOT(slotInsertMarkVariableText()) ); + connect( (*scrActions)["insertMarkItem"], SIGNAL(triggered()), mainWindow, SLOT(slotInsertMarkItem()) ); + connect( (*scrActions)["insertMark2Mark"], SIGNAL(triggered()), mainWindow, SLOT(slotInsertMark2Mark()) ); + connect( (*scrActions)["insertMarkNote"], SIGNAL(triggered()), mainWindow, SLOT(slotInsertMarkNote()) ); +// connect( (*scrActions)["insertMarkIndex"], SIGNAL(triggered()), mainWindow, SLOT(slotInsertMarkIndex()) ); + connect( (*scrActions)["editMark"], SIGNAL(triggered()), mainWindow, SLOT(slotEditMark()) ); + connect( (*scrActions)["itemUpdateMarks"], SIGNAL(triggered()), mainWindow, SLOT(slotUpdateMarks()) ); } void ActionManager::initPageMenuActions() @@ -1413,6 +1454,8 @@ void ActionManager::languageChange() // (*scrActions)["editPatterns"]->setTexts( tr("Patterns...")); // (*scrActions)["editGradients"]->setTexts( tr("Gradients...")); (*scrActions)["editStyles"]->setTexts( tr("S&tyles...")); + (*scrActions)["editMarks"]->setTexts( tr("Marks...")); + (*scrActions)["editNotesStyles"]->setTexts( tr("Notes Styles...")); (*scrActions)["editMasterPages"]->setTexts( tr("&Master Pages...")); (*scrActions)["editJavascripts"]->setTexts( tr("&JavaScripts...")); @@ -1508,6 +1551,14 @@ void ActionManager::languageChange() (*scrActions)["insertGlyph"]->setTexts( tr("&Glyph...")); (*scrActions)["insertSampleText"]->setTexts( tr("Sample Text")); (*scrActions)["stickyTools"]->setTexts( tr("Sticky Tools")); + (*scrActions)["insertMarkAnchor"]->setTexts( tr("Anchor Mark")); + (*scrActions)["insertMarkVariableText"]->setTexts( tr("Variable Text")); + (*scrActions)["insertMarkItem"]->setTexts( tr("Reference to Item")); + (*scrActions)["insertMark2Mark"]->setTexts( tr("Reference to Mark")); + (*scrActions)["insertMarkNote"]->setTexts( tr("Foot/Endnote")); +// (*scrActions)["insertMarkIndex"]->setTexts( tr("Index entry")); + (*scrActions)["editMark"]->setTexts( tr("Edit Mark")); + (*scrActions)["itemUpdateMarks"]->setTexts( tr("Update Marks")); //Page menu (*scrActions)["pageInsert"]->setTexts( tr("&Insert...")); @@ -1900,6 +1951,8 @@ void ActionManager::createDefaultMenus() << "editReplaceColors" // << "editPatterns" << "editStyles" + << "editMarks" + << "editNotesStyles" << "editMasterPages" << "editJavascripts"; //Style @@ -2008,7 +2061,15 @@ void ActionManager::createDefaultMenus() << "toolsInsertRenderFrame" << "stickyTools" << "insertGlyph" - << "insertSampleText"; + << "insertSampleText" + << "insertMarkAnchor" + << "insertMarkVariableText" + << "insertMarkItem" + << "insertMark2Mark" + << "insertMarkNote" + << "insertMarkIndex" + << "editMark" + << "itemUpdateMarks"; itmenu->second << "unicodeSoftHyphen" diff --git Scribus/scribus/canvas.cpp Scribus/scribus/canvas.cpp index 1eb528e..4b1a909 100644 --- Scribus/scribus/canvas.cpp +++ Scribus/scribus/canvas.cpp @@ -1035,7 +1035,10 @@ void Canvas::drawContents(QPainter *psx, int clipx, int clipy, int clipw, int cl { DrawMasterItems(painter, m_doc->Pages->at(a), layer, QRect(clipx, clipy, clipw, cliph)); } - DrawPageItems(painter, layer, QRect(clipx, clipy, clipw, cliph)); + //first pass draws all except notes frames + DrawPageItems(painter, layer, QRect(clipx, clipy, clipw, cliph), false); + //seconf only for notes frames + DrawPageItems(painter, layer, QRect(clipx, clipy, clipw, cliph), true); } } } @@ -1076,7 +1079,10 @@ void Canvas::drawContents(QPainter *psx, int clipx, int clipy, int clipw, int cl for (int layerLevel = 0; layerLevel < layerCount; ++layerLevel) { m_doc->Layers.levelToLayer(layer, layerLevel); - DrawPageItems(painter, layer, QRect(clipx, clipy, clipw, cliph)); + //first pass draws all except notes frames + DrawPageItems(painter, layer, QRect(clipx, clipy, clipw, cliph), false); + //second pass draw only notes frames + DrawPageItems(painter, layer, QRect(clipx, clipy, clipw, cliph), true); } } } @@ -1445,7 +1451,7 @@ void Canvas::DrawMasterItems(ScPainter *painter, ScPage *page, ScLayer& layer, Q /** draws page items contained in a specific Layer */ -void Canvas::DrawPageItems(ScPainter *painter, ScLayer& layer, QRect clip) +void Canvas::DrawPageItems(ScPainter *painter, ScLayer& layer, QRect clip, bool notesFramesPass) { if ((m_viewMode.previewMode) && (!layer.isPrintable)) return; @@ -1466,9 +1472,34 @@ void Canvas::DrawPageItems(ScPainter *painter, ScLayer& layer, QRect clip) int docCurrPageNo=static_cast<int>(m_doc->currentPageNumber()); if ((layerCount > 1) && ((layer.blendMode != 0) || (layer.transparency != 1.0)) && (!layer.outlineMode)) painter->beginLayer(layer.transparency, layer.blendMode); + + //if notes are used + //then we must be sure that text frames are valid and all notes frames are created before we start drawing + if (!notesFramesPass && !m_doc->notesList().isEmpty()) + { for (int it = 0; it < m_doc->Items->count(); ++it) { currItem = m_doc->Items->at(it); + if ( !currItem->isTextFrame() + || currItem->isNoteFrame() + || !currItem->invalid + || (currItem->LayerID != layer.ID) + || (m_viewMode.previewMode && !currItem->printEnabled()) + || (m_viewMode.viewAsPreview && (!currItem->printEnabled())) + || (m_doc->masterPageMode() && ((currItem->OwnPage != -1) && (currItem->OwnPage != docCurrPageNo))) + || ((!m_doc->masterPageMode() && !currItem->OnMasterPage.isEmpty()) && (currItem->OnMasterPage != m_doc->currentPage()->pageName()))) + continue; + if (cullingArea.intersects(currItem->getBoundingRect().adjusted(0.0, 0.0, 1.0, 1.0))) + currItem->layout(); + } + } + for (int it = 0; it < m_doc->Items->count(); ++it) + { + currItem = m_doc->Items->at(it); + if (notesFramesPass && !currItem->isNoteFrame()) + continue; + if (!notesFramesPass && currItem->isNoteFrame()) + continue; if (currItem->LayerID != layer.ID) continue; if ((m_viewMode.previewMode) && (!currItem->printEnabled())) diff --git Scribus/scribus/canvas.h Scribus/scribus/canvas.h index bb10500..79dc1e5 100644 --- Scribus/scribus/canvas.h +++ Scribus/scribus/canvas.h @@ -195,7 +195,8 @@ public: void setPreviewVisual(int mode); void DrawMasterItems(ScPainter *painter, ScPage *page, ScLayer& layer, QRect clip); - void DrawPageItems(ScPainter *painter, ScLayer& layer, QRect clip); + //notesFramesPass determine if notes frames are drawed or not + void DrawPageItems(ScPainter *painter, ScLayer& layer, QRect clip, bool notesFramesPass); virtual void paintEvent ( QPaintEvent * p ); void displayXYHUD(QPoint m); void displayCorrectedXYHUD(QPoint m, double x, double y); diff --git Scribus/scribus/canvasmode_edit.cpp Scribus/scribus/canvasmode_edit.cpp index 3a8b3d0..4793c5d 100644 --- Scribus/scribus/canvasmode_edit.cpp +++ Scribus/scribus/canvasmode_edit.cpp @@ -315,6 +315,11 @@ void CanvasMode_Edit::mouseDoubleClickEvent(QMouseEvent *m) currItem->itemText.extendSelection(start, stop); currItem->itemText.setCursorPosition(stop); } + else if ((currItem->itemText.cursorPosition() < currItem->itemText.length()) && (currItem->itemText.item(currItem->itemText.cursorPosition())->mark != NULL)) + { //invoke edit marker dialog + m_ScMW->slotEditMark(); + return; + } else { //Double click in a frame to select a word oldCp = currItem->itemText.cursorPosition(); @@ -443,7 +448,7 @@ void CanvasMode_Edit::mouseMoveEvent(QMouseEvent *m) int hitTest = m_canvas->frameHitTest(QPointF(mousePointDoc.x(),mousePointDoc.y()), currItem); if(hitTest >= 0) { - if((hitTest == Canvas::INSIDE)) + if(hitTest == Canvas::INSIDE) { if (currItem->asTextFrame()) qApp->changeOverrideCursor(QCursor(Qt::IBeamCursor)); diff --git Scribus/scribus/canvasmode_normal.cpp Scribus/scribus/canvasmode_normal.cpp index 7cf09ab..a73d90d 100644 --- Scribus/scribus/canvasmode_normal.cpp +++ Scribus/scribus/canvasmode_normal.cpp @@ -241,6 +241,9 @@ void CanvasMode_Normal::mouseDoubleClickEvent(QMouseEvent *m) { m_view->requestMode(modeEdit); m_view->slotSetCurs(m->globalPos().x(), m->globalPos().y()); + //used for updating Notes Styles Editor and menu actions for marks + //if cursor is in mark`s place + m_ScMW->setTBvals(currItem); //CB ignore the double click and go with a single one //if we werent in mode edit before. //unsure if this is correct, but its ok given we had no @@ -716,8 +719,12 @@ void CanvasMode_Normal::mouseMoveEvent(QMouseEvent *m) if(currItem->asLine()) qApp->changeOverrideCursor(QCursor(Qt::SizeAllCursor)); else if(!currItem->locked() && !currItem->sizeLocked()) + { + if ((!currItem->sizeHLocked() && !currItem->sizeVLocked()) || (currItem->sizeHLocked() && (how == 5 || how == 8)) + || (currItem->sizeVLocked() && (how == 6 || how == 7))) setResizeCursor(how, currItem->rotation()); } + } else if (how == 0) qApp->changeOverrideCursor(QCursor(Qt::OpenHandCursor)); else diff --git Scribus/scribus/documentchecker.cpp Scribus/scribus/documentchecker.cpp index 46b813a..238a083 100644 --- Scribus/scribus/documentchecker.cpp +++ Scribus/scribus/documentchecker.cpp @@ -98,6 +98,10 @@ bool DocumentChecker::checkDocument(ScribusDoc *currDoc) if (layerError.count() != 0) currDoc->docLayerErrors.insert(ll.ID, layerError); } + + //update all marks references and check if that changes anything in doc + currDoc->setNotesChanged(currDoc->updateMarks(true)); + QList<PageItem*> allItems; uint masterItemsCount = currDoc->MasterItems.count(); for (uint i = 0; i < masterItemsCount; ++i) diff --git Scribus/scribus/fonts/scface.cpp Scribus/scribus/fonts/scface.cpp index 653dde7..ffa91e6 100644 --- Scribus/scribus/fonts/scface.cpp +++ Scribus/scribus/fonts/scface.cpp @@ -343,7 +343,7 @@ uint ScFace::emulateGlyph(QChar ch) const if (ch == SpecialChars::LINEBREAK || ch == SpecialChars::PARSEP || ch == SpecialChars::FRAMEBREAK || ch == SpecialChars::COLBREAK || ch == SpecialChars::TAB || ch == SpecialChars::SHYPHEN - || ch == SpecialChars::ZWSPACE || ch == SpecialChars::ZWNBSPACE) + || ch == SpecialChars::ZWSPACE || ch == SpecialChars::ZWNBSPACE || ch==SpecialChars::OBJECT) return CONTROL_GLYPHS + ch.unicode(); else if (ch == SpecialChars::NBSPACE) return m->char2CMap(QChar(' ')); diff --git Scribus/scribus/marks.h Scribus/scribus/marks.h new file mode 100644 index 0000000..e6988f7 --- /dev/null +++ Scribus/scribus/marks.h @@ -0,0 +1,98 @@ +#ifndef MARKS_H +#define MARKS_H + +#include "QString" +#include "scribusapi.h" +#include "desaxe/saxiohelper.h" +#include "desaxe/simple_actions.h" + +class Mark; +class PageItem; +class TextNote; + +enum MarkType +{ + MARKNoType = -1, //undefinied mark type (wrong situation!) + MARKAnchorType = 0, //empty anchor mark, useful for creating references to it + MARK2ItemType = 1, //reference to page item ID + MARK2MarkType = 2, //reference other mark + MARKVariableTextType = 3,//mark contain dynamic text + MARKNoteMasterType = 4, //mark contain footnote reference + MARKNoteFrameType = 5, //mark used internally in note frame at beginning of note`s text + MARKIndexType = 6 // index entry +}; + +struct MarkData +{ + QString strtxt; + PageItem* itemPtr; + QString destmarkName; + MarkType destmarkType; + TextNote* notePtr; + //fields used for resolving to pointers for load and copy + QString itemName; + MarkType markTyp; + + MarkData() : strtxt(""), itemPtr(NULL), destmarkName(""), destmarkType(MARKNoType), notePtr(NULL), itemName(""), markTyp(MARKNoType) {} +}; + +class SCRIBUS_API Mark +{ + friend class ScribusDoc; + friend class ScribusMainWindow; + //only ScribusDoc && ScribusMainWindow can create and delete marks +private: + Mark() : label(""), OwnPage(-1), typ(MARKNoType), data() {} + Mark(const Mark& other) : label(other.label), OwnPage(other.OwnPage), typ(other.typ), data(other.data) {} + ~Mark() {} +public: + QString label; + int OwnPage; + + void setValues(QString l, int p, MarkType t, MarkData d) { label = l; OwnPage = p; typ = t; data = d; } + const MarkType getType() { return typ; } + void setType(MarkType t) { typ = t; } + const MarkData getData() { return data; } + void setData(const MarkData d) { data = d; } + PageItem* getItemPtr() { return data.itemPtr; } + void setItemPtr( PageItem* ptr ) { data.itemPtr = ptr; } + const QString getItemName() { return data.itemName; } + void setItemName( const QString name ) { data.itemName = name; } + + //for marks to marks - return label and type of target mark by reference + const void getMark(QString &l, MarkType &t) { l = data.destmarkName; t = data.destmarkType; } + //for marks to marks - set label and type of target mark from mark pointer + void setMark(Mark* mP) + { + if (mP == NULL) + { + data.destmarkName = ""; + data.destmarkType = MARKNoType; + } + else + { + data.destmarkName = mP->label; + data.destmarkType = mP->getType(); + } + } + void setMark(QString l, MarkType t) { data.destmarkName = l; data.destmarkType = t; } + const MarkType getMarkType() { return data.markTyp; } + void setMarkType(MarkType t) { data.markTyp = t; } + const QString getString() { return data.strtxt; } + void setString( const QString str ) { data.strtxt = str; } + TextNote* getNotePtr() { return data.notePtr; } + void setNotePtr(TextNote *note) { data.notePtr = note; } + + bool hasItemPtr() { return data.itemPtr != NULL; } + bool hasString() { return !data.strtxt.isEmpty(); } + bool hasMark() { return data.destmarkName != ""; } + bool isUnique() { return ((typ != MARKVariableTextType) && (typ != MARKIndexType)); } + bool isNoteType() { return ((typ == MARKNoteMasterType) || (typ==MARKNoteFrameType)); } + bool isType(const MarkType t) { return t==typ; } + +protected: + MarkType typ; + MarkData data; +}; + +#endif // MARKS_H diff --git Scribus/scribus/notesstyles.cpp Scribus/scribus/notesstyles.cpp new file mode 100644 index 0000000..f4a2a91 --- /dev/null +++ Scribus/scribus/notesstyles.cpp @@ -0,0 +1,22 @@ +#include "notesstyles.h" +#include "marks.h" + +void NotesStyle::setEndNotes(bool setendnotes) +{ + if (m_endNotesStyle != setendnotes) + { + m_endNotesStyle = setendnotes; + } +} + +bool NotesStyle::operator!=(const NotesStyle& n2) +{ + return ((nameStr != n2.nameStr) || (startNum != n2.startNum) || (m_endNotesStyle != n2.m_endNotesStyle) || + (getType() != static_cast<NotesStyle>(n2).getType()) || (numRange != n2.numRange) || + (prefixStr != n2.prefixStr) || (suffixStr != n2.suffixStr) || + (autoNotesHeight != n2.autoNotesHeight) || (autoNotesWidth != n2.autoNotesWidth) || + (autoRemoveEmptyNotesFrames != n2.autoRemoveEmptyNotesFrames) || (autoWeldNotesFrames != n2.autoWeldNotesFrames) || + (superscriptInMaster != n2.superscriptInMaster) || (superscriptInNote != n2.superscriptInNote) || + (marksCharStyle != n2.marksCharStyle) || (notesParaStyle != n2.notesParaStyle) + ); +} diff --git Scribus/scribus/notesstyles.h Scribus/scribus/notesstyles.h new file mode 100644 index 0000000..911cb94 --- /dev/null +++ Scribus/scribus/notesstyles.h @@ -0,0 +1,141 @@ +#ifndef NOTESSTYLES_H +#define NOTESSTYLES_H + +#include <QDebug> +#include <QObject> +#include <QString> +#include <QList> +#include "pagestructs.h" +#include "scpage.h" +#include "styles/charstyle.h" +#include "styles/paragraphstyle.h" +#include "text/storytext.h" +#include "util.h" + +class ScribusDoc; +class PageItem_NoteFrame; +class PageItem_TextFrame; + +class Numeration +{ +public: + Numeration() : numType(Type_1_2_3) {} + void setType(NumerationType type) { numType = type; } + const NumerationType type() { return numType; } + const QString numString(const int num) { return getStringFromSequence(numType, num); } +private: + NumerationType numType; +}; + +typedef enum { + NSRdocument, + NSRsection, + NSRstory, + NSRpage, + NSRframe +} NumerationRange; + +//used for map with endnotes frames maped with range item +typedef union +{ + void* P; + int sectionIndex; + ScPage* page; + PageItem_TextFrame* firstStoryFrame; +} rangeItem; + +class SCRIBUS_API NotesStyle +{ +public: + NotesStyle() : nameStr ("default"), startNum(1), m_endNotesStyle(false), numeration(), numRange(NSRdocument), prefixStr(""), suffixStr(")"), + autoNotesHeight(true), autoNotesWidth(true), autoRemoveEmptyNotesFrames(true), autoWeldNotesFrames(true), + superscriptInNote(true), superscriptInMaster(true), marksCharStyle(""), notesParaStyle("") {} + ~NotesStyle() {} + bool operator!=(const NotesStyle& n2); + + const QString name() { return nameStr; } + void setName(const QString s) { nameStr = s; } + const int start() { return startNum; } + void setStart(const int i) { startNum = i; } + void setRange(NumerationRange ns) { numRange = ns; } + const NumerationRange range() { return numRange; } + const QString prefix() { return prefixStr; } + void setPrefix (const QString str) { prefixStr = str; } + const QString suffix() { return suffixStr; } + void setSuffix (const QString str) { suffixStr = str; } + + const QString numString(const int num) { return numeration.numString(num); } + void setType(const NumerationType type) { numeration.setType(type); } + const NumerationType getType() { return numeration.type(); } + + bool isEndNotes() { return m_endNotesStyle; } + bool isAutoNotesHeight() { return autoNotesHeight; } + void setAutoNotesHeight(const bool set) { autoNotesHeight = set; } + bool isAutoNotesWidth() { return autoNotesWidth; } + void setAutoNotesWidth(const bool set) { autoNotesWidth = set; } + bool isAutoRemoveEmptyNotesFrames() { return autoRemoveEmptyNotesFrames; } + void setAutoRemoveEmptyNotesFrames(const bool set) { autoRemoveEmptyNotesFrames = set; } + bool isAutoWeldNotesFrames() { return autoWeldNotesFrames; } + void setAutoWeldNotesFrames(const bool set) { autoWeldNotesFrames = set; } + bool isSuperscriptInNote() { return superscriptInNote; } + void setSuperscriptInNote(const bool set) { superscriptInNote = set; } + bool isSuperscriptInMaster() { return superscriptInMaster; } + void setSuperscriptInMaster(const bool set) { superscriptInMaster = set; } + const QString marksChStyle() { return marksCharStyle; } + void setMarksCharStyle(const QString styleName) { marksCharStyle = styleName; } + const QString notesParStyle() { return notesParaStyle; } + void setNotesParStyle(const QString styleName) { notesParaStyle = styleName; } + + void setEndNotes(bool); + +private: + QString nameStr; //unique name of notes style + int startNum; //numeration starts with that number + + bool m_endNotesStyle; //if not true this is set of footnotes + Numeration numeration; + NumerationRange numRange; //range of numeration for current set + QString prefixStr; + QString suffixStr; + bool autoNotesHeight; //change height of notes frames to its content automaticaly? + bool autoNotesWidth; //change width of notes frames automaticaly if width of master frame changes? + bool autoRemoveEmptyNotesFrames; + bool autoWeldNotesFrames; + bool superscriptInNote; + bool superscriptInMaster; + QString marksCharStyle; + QString notesParaStyle; +}; + +class SCRIBUS_API TextNote : public QObject +{ + Q_OBJECT + friend class ScribusDoc; +private: + //only ScribusDoc can create and delete notes + TextNote(NotesStyle *nStyle) : _notesStyle(nStyle), _noteSaxedText(""), _noteMasterMark(NULL), _noteFrameMark(NULL), _number(0) { } + ~TextNote() {} +public: + void setNotesStyle (NotesStyle* NS) { _notesStyle = NS; } + NotesStyle* notesStyle() { return _notesStyle; } + const int num() { return _number; } + void setNum(const int x) { _number = x; } + const QString numString() { return notesStyle()->numString(_number); } + Mark* masterMark() { return _noteMasterMark; } + void setMasterMark(Mark* MRK) { _noteMasterMark = MRK; } + Mark* noteMark() { return _noteFrameMark; } + void setNoteMark(Mark* MRK) { _noteFrameMark = MRK; } + const QString saxedText() { return _noteSaxedText; } + void setSaxedText(const QString string) { _noteSaxedText = string; } + bool isEndNote() { return _notesStyle->isEndNotes(); } + int textLen; + +protected: + NotesStyle *_notesStyle; + QString _noteSaxedText; + Mark *_noteMasterMark; + Mark *_noteFrameMark; + int _number; +}; + +#endif // NOTESSTYLES_H diff --git Scribus/scribus/pageitem.cpp Scribus/scribus/pageitem.cpp index 2724d5e..4605ed0 100644 --- Scribus/scribus/pageitem.cpp +++ Scribus/scribus/pageitem.cpp @@ -35,18 +35,22 @@ for which a new license (GPL+exception) is in place. #include <QMessageBox> #include <QPolygon> #include <cassert> +#include <sstream> #include <QDebug> #include "canvas.h" #include "cmsettings.h" #include "colorblind.h" #include "commonstrings.h" +#include "desaxe/saxXML.h" +#include "marks.h" #include "pageitem_group.h" #include "pageitem_regularpolygon.h" #include "pageitem_arc.h" #include "pageitem_spiral.h" #include "pageitem_textframe.h" +#include "pageitem_noteframe.h" #include "pageitem_latexframe.h" #include "prefsmanager.h" @@ -244,6 +248,8 @@ PageItem::PageItem(const PageItem & other) m_ImageIsFlippedV(other.m_ImageIsFlippedV), m_Locked(other.m_Locked), m_SizeLocked(other.m_SizeLocked), + m_SizeHLocked(other.m_SizeHLocked), + m_SizeVLocked(other.m_SizeVLocked), textFlowModeVal(other.textFlowModeVal), pageItemAttributes(other.pageItemAttributes), m_PrintEnabled(other.m_PrintEnabled), @@ -382,6 +388,8 @@ PageItem::PageItem(ScribusDoc *pa, ItemType newType, double x, double y, double m_ImageIsFlippedV(0), m_Locked(false), m_SizeLocked(false), + m_SizeHLocked(false), + m_SizeVLocked(false), textFlowModeVal(TextFlowDisabled) { Parent = NULL; @@ -828,6 +836,32 @@ PageItem::PageItem(ScribusDoc *pa, ItemType newType, double x, double y, double isInlineImage = false; } +PageItem::~PageItem() +{ + if (tempImageFile != NULL) + delete tempImageFile; + //remove marks + + if (isTextFrame()) + { + if (!asTextFrame()->isInChain() && itemText.length() >0) + { + for (int pos=0; pos < itemText.length(); ++pos) + { + if (itemText.item(pos)->hasMark()) + { + Mark* mrk = itemText.item(pos)->mark; + m_Doc->eraseMark(mrk); + } + } + } + } +// if (isWeld()) +// unWeldFromMaster(true); +// if (isWelded()) +// unWeldChild(); +} + void PageItem::setXPos(const double newXPos, bool drawingOnly) { Xpos = newXPos; @@ -884,8 +918,8 @@ void PageItem::moveBy(const double dX, const double dY, bool drawingOnly) } if (drawingOnly || m_Doc->isLoading()) return; - checkChanges(); moveWelded(dX, dY); + checkChanges(); } void PageItem::setWidth(const double newWidth) @@ -947,8 +981,8 @@ void PageItem::setRotation(const double newRotation, bool drawingOnly) Rot = newRotation; if (drawingOnly || m_Doc->isLoading()) return; - checkChanges(); rotateWelded(dR, oldRot); + checkChanges(); } void PageItem::rotateBy(const double dR) @@ -2275,6 +2309,13 @@ QString PageItem::ExpandToken(uint base) else return "%"; } + //check for marks + else if (ch == SpecialChars::OBJECT) + { + ScText* hl = itemText.item(base); + if ((hl->mark != NULL) && !hl->mark->isType(MARKAnchorType) && !hl->mark->isType(MARKIndexType)) + chstr = hl->mark->getString(); + } return chstr; } @@ -2460,6 +2501,13 @@ void PageItem::drawGlyphs(ScPainter *p, const CharStyle& style, GlyphLayout& gly points.addQuadPoint(0, -10, 0, -10, 0, -6, 0, -6); stroke = true; } + else if (glyph == SpecialChars::OBJECT.unicode()) + { + //for showing marks entries as control chars + points.resize(0); + points.addQuadPoint(0, -8, 1, -8, 0, -6, 1, -6); + stroke = true; + } else // ??? { points.resize(0); @@ -4627,27 +4675,47 @@ void PageItem::resizeUndoAction() { if (oldHeight == Height && oldWidth == Width) return; - if (UndoManager::undoEnabled()) + bool doUndo = true; + if (isNoteFrame() + && ((asNoteFrame()->isAutoHeight() && asNoteFrame()->isAutoWidth()) + || ((oldHeight == Height) && asNoteFrame()->isAutoWidth()) + || ((oldWidth == Width) && asNoteFrame()->isAutoHeight()))) + doUndo = false; + if (doUndo && UndoManager::undoEnabled()) { SimpleState *ss = new SimpleState(Um::Resize, QString(Um::ResizeFromTo).arg(oldWidth).arg(oldHeight).arg(Width).arg(Height), Um::IResize); + if (!isNoteFrame() || !asNoteFrame()->isAutoWidth()) + { ss->set("OLD_WIDTH", oldWidth); - ss->set("OLD_HEIGHT", oldHeight); ss->set("NEW_WIDTH", Width); + } + if (!isNoteFrame() || !asNoteFrame()->isAutoHeight()) + { + ss->set("OLD_HEIGHT", oldHeight); ss->set("NEW_HEIGHT", Height); + } + if (!isNoteFrame() || !asNoteFrame()->isAutoWelded()) + { ss->set("OLD_RXPOS", oldXpos); ss->set("OLD_RYPOS", oldYpos); ss->set("NEW_RXPOS", Xpos); ss->set("NEW_RYPOS", Ypos); + } ss->set("OLD_RROT", oldRot); ss->set("NEW_RROT", Rot); undoManager->action(this, ss); } + if (!isNoteFrame() || !asNoteFrame()->isAutoWidth()) + oldWidth = Width; + if (!isNoteFrame() || !asNoteFrame()->isAutoHeight()) + oldHeight = Height; + if (!isNoteFrame() || !asNoteFrame()->isAutoWelded()) + { oldXpos = Xpos; oldYpos = Ypos; - oldHeight = Height; - oldWidth = Width; + } oldOwnPage = OwnPage; oldRot = Rot; } @@ -4663,14 +4731,23 @@ void PageItem::rotateUndoAction() Um::IRotate); ss->set("OLD_ROT", oldRot); ss->set("NEW_ROT", Rot); + if (!isNoteFrame() || !asNoteFrame()->isAutoWelded()) + { ss->set("OLD_RXPOS", oldXpos); ss->set("OLD_RYPOS", oldYpos); ss->set("NEW_RXPOS", Xpos); ss->set("NEW_RYPOS", Ypos); - ss->set("OLD_RWIDTH", oldWidth); + } + if (!isNoteFrame() || !asNoteFrame()->isAutoHeight()) + { ss->set("OLD_RHEIGHT", oldHeight); - ss->set("NEW_RWIDTH", Width); ss->set("NEW_RHEIGHT", Height); + } + if (!isNoteFrame() || !asNoteFrame()->isAutoWidth()) + { + ss->set("NEW_RWIDTH", Width); + ss->set("OLD_RWIDTH", oldWidth); + } undoManager->action(this, ss); } oldRot = Rot; @@ -4753,7 +4830,7 @@ void PageItem::restore(UndoState *state, bool isUndo) restoreStartArrowScale(ss, isUndo); else if (ss->contains("IMAGE_ROTATION")) restoreImageRotation(ss, isUndo); - else if (ss->contains("OLD_HEIGHT")) + else if (ss->contains("OLD_HEIGHT") || ss->contains("OLD_WIDTH")) restoreResize(ss, isUndo); else if (ss->contains("OLD_ROT")) restoreRotate(ss, isUndo); @@ -4883,6 +4960,8 @@ void PageItem::restore(UndoState *state, bool isUndo) restoreArrow(ss, isUndo, true); else if (ss->contains("END_ARROW")) restoreArrow(ss, isUndo, false); + else if (ss->contains("PSTYLE")) + restorePStyle(ss, isUndo); else if (ss->contains("CONVERT")) restoreType(ss, isUndo); else if (ss->contains("TEXTFLOW_OLDMODE")) @@ -4951,6 +5030,10 @@ void PageItem::restore(UndoState *state, bool isUndo) restoreAppMode(ss, isUndo); else if (ss->contains("CONNECT_PATH")) restoreConnectPath(ss, isUndo); + else if (ss->contains("WELD_ITEMS")) + restoreWeldItems(ss, isUndo); + else if (ss->contains("UNWELD_ITEM")) + restoreUnWeldItem(ss, isUndo); } if (!OnMasterPage.isEmpty()) m_Doc->setCurrentPage(oldCurrentPage); @@ -4981,6 +5064,51 @@ void PageItem::restoreConnectPath(SimpleState *state, bool isUndo) ContourLine = PoLine.copy(); } +void PageItem::restoreWeldItems(SimpleState *state, bool isUndo) +{ + if (isUndo) + { + unWeld(); + } + else + { + ScItemState<PageItem*> *is = dynamic_cast<ScItemState<PageItem*>*>(state); + PageItem* wIt = is->getItem(); + weldTo(wIt); + } + m_Doc->changed(); + m_Doc->regionsChanged()->update(QRectF()); +} + +void PageItem::restoreUnWeldItem(SimpleState *state, bool isUndo) +{ + if (isUndo) + { + ScItemState<PageItem*> *is = dynamic_cast<ScItemState<PageItem*>*>(state); + PageItem* wIt = is->getItem(); + { + weldingInfo wInf; + wInf.weldItem = wIt; + wInf.weldID = is->getInt("thisID"); + wInf.weldPoint = FPoint(is->getDouble("thisPoint_x"), is->getDouble("thisPoint_y")); + weldList.append(wInf); + } + { + weldingInfo wInf; + wInf.weldItem = this; + wInf.weldID = is->getInt("ID"); + wInf.weldPoint = FPoint(is->getDouble("Point_x"), is->getDouble("Point_y")); + wIt->weldList.append(wInf); + } + } + else + { + unWeld(); + } + m_Doc->changed(); + m_Doc->regionsChanged()->update(QRectF()); +} + bool PageItem::checkGradientUndoRedo(SimpleState *ss, bool isUndo) { if (ss->contains("SNAP_TO_PATCH")) @@ -6281,6 +6409,7 @@ void PageItem::restoreDeleteFrameText(SimpleState *ss, bool isUndo) itemText.select(start,text.length()); asTextFrame()->deleteSelectedTextFromFrame(); } + update(); } void PageItem::restoreInsertFrameText(SimpleState *ss, bool isUndo) @@ -6537,6 +6666,17 @@ void PageItem::restoreArrow(SimpleState *state, bool isUndo, bool isStart) setEndArrowIndex(i); } + +void PageItem::restorePStyle(SimpleState *state, bool isUndo) +{ + int styleid = state->getInt("OLD_STYLE"); + if (!isUndo) + styleid = state->getInt("NEW_STYLE"); + //will be done later with other text-undo: + // m_Doc->chAbStyle(this, styleid); +} + + // FIXME: This must go into class ScribusDoc! // For now we'll just make it independent of 'this' -- AV void PageItem::restoreType(SimpleState *state, bool isUndo) @@ -7067,7 +7207,8 @@ void PageItem::setObjectAttributes(ObjAttrVector* map) pageItemAttributes=*map; } -QString PageItem::generateUniqueCopyName(const QString originalName) const +//if not `prependCopy` then string "Copy of" wil not be prepended +QString PageItem::generateUniqueCopyName(const QString originalName, bool prependCopy) const { if (!m_Doc->itemNameExists(originalName)) return originalName; @@ -7075,7 +7216,7 @@ QString PageItem::generateUniqueCopyName(const QString originalName) const // Start embellishing the name until we get an acceptable unique name // first we prefix `Copy of' if it's not already there QString newname(originalName); - if (!originalName.startsWith( tr("Copy of"))) + if (prependCopy && !originalName.startsWith( tr("Copy of"))) newname.prepend( tr("Copy of")+" "); // See if the name prefixed by "Copy of " is free @@ -9371,6 +9512,24 @@ void PageItem::setFileIconRollover(QString val) } } +PageItem* PageItem::firstInChain() +{ + Q_ASSERT(this != NULL); + PageItem* first = this; + while (first->prevInChain() != NULL) + first = first->prevInChain(); + return first; +} + +PageItem* PageItem::lastInChain() +{ + Q_ASSERT(this != NULL); + PageItem* last = this; + while (last->nextInChain() != NULL) + last = last->nextInChain(); + return last; +} + QRect PageItem::getRedrawBounding(const double viewScale) { int x = qRound(floor(BoundingX - Oldm_lineWidth / 2.0 - 5) * viewScale); @@ -9719,7 +9878,8 @@ void PageItem::convertClip() } } -void PageItem::updateClip() +//udateWelded determine if welded items should be updated as well (default behaviour) +void PageItem::updateClip(bool updateWelded) { if (m_Doc->appMode == modeDrawBezierLine) return; @@ -9829,9 +9989,30 @@ void PageItem::updateClip() else Clip = FlattenPath(PoLine, Segments); } + if (updateWelded) + { for (int i = 0 ; i < weldList.count(); i++) { weldingInfo wInf = weldList.at(i); + if (wInf.weldItem->isNoteFrame()) + { + PageItem_NoteFrame* noteFrame = wInf.weldItem->asNoteFrame(); + if (noteFrame->notesStyle()->isAutoWeldNotesFrames()) + { + if (noteFrame->notesStyle()->isAutoNotesWidth()) + { + if (noteFrame->width() != width()) + { + noteFrame->setWidth(width()); + noteFrame->updateClip(); + } + } + noteFrame->setXYPos(xPos(),yPos() + height()); + setWeldPoint(0, height(), noteFrame); + noteFrame->setWeldPoint(0,0, this); + continue; + } + } FPointArray gr4; FPoint wp = wInf.weldPoint; gr4.addPoint(wp); @@ -9843,6 +10024,7 @@ void PageItem::updateClip() weldList[i] = wInf; } } + } OldB2 = width(); OldH2 = height(); if ((FrameType < 3) && (!ClipEdited)) @@ -9942,9 +10124,29 @@ void PageItem::updateClip() Clip = FlattenPath(PoLine, Segments); OldB2 = width(); OldH2 = height(); + if (updateWelded) + { for (int i = 0 ; i < weldList.count(); i++) { weldingInfo wInf = weldList.at(i); + if (wInf.weldItem->isNoteFrame()) + { + PageItem_NoteFrame* noteFrame = wInf.weldItem->asNoteFrame(); + if (noteFrame->notesStyle()->isAutoWeldNotesFrames()) + { + if (noteFrame->notesStyle()->isAutoNotesWidth()) + { + if (noteFrame->width() != width()) + { + noteFrame->setWidth(width()); + noteFrame->updateClip(); + } + } + setWeldPoint(0, height(), noteFrame); + noteFrame->setWeldPoint(0,0, this); + continue; + } + } FPointArray gr4; FPoint wp = wInf.weldPoint; gr4.addPoint(wp); @@ -9956,6 +10158,7 @@ void PageItem::updateClip() weldList[i] = wInf; } } + } break; } updateGradientVectors(); @@ -10064,12 +10267,21 @@ void PageItem::weldTo(PageItem* pIt) return; addWelded(pIt); pIt->addWelded(this); + if(undoManager->undoEnabled()) + { + ScItemState<PageItem*> *is = new ScItemState<PageItem*>(Um::WeldItems,"",Um::IGroup); + is->set("WELD_ITEMS", "weld_items"); + is->setItem(pIt); + undoManager->action(this, is, getUPixmap()); + } update(); pIt->update(); } void PageItem::moveWelded(double DX, double DY, int weld) { + if ((DX == 0) && (DY == 0)) + return; weldingInfo wInf = weldList.at(weld); PageItem *pIt = wInf.weldItem; pIt->setXPos(pIt->xPos() + DX); @@ -10080,6 +10292,10 @@ void PageItem::moveWelded(double DX, double DY, int weld) void PageItem::moveWelded(double DX, double DY, PageItem* except) { + if ((DX == 0) && (DY == 0)) + return; + //do not save undo for auto-welded notes frames + UndoManager::instance()->setUndoEnabled(false); for (int i = 0 ; i < weldList.count(); i++) { weldingInfo wInf = weldList.at(i); @@ -10092,10 +10308,12 @@ void PageItem::moveWelded(double DX, double DY, PageItem* except) pIt->moveWelded(DX, DY, this); } } + UndoManager::instance()->setUndoEnabled(true); } void PageItem::rotateWelded(double dR, double oldRot) { + UndoManager::instance()->setUndoEnabled(false); QTransform ma; ma.translate(xPos(), yPos()); ma.scale(1, 1); @@ -10125,6 +10343,7 @@ void PageItem::rotateWelded(double dR, double oldRot) pIt->setXYPos(lin.p2().x(), lin.p2().y()); pIt->rotateBy(dR); } + UndoManager::instance()->setUndoEnabled(true); } QList<PageItem*> PageItem::itemsWeldedTo(PageItem* except) @@ -10145,12 +10364,34 @@ QList<PageItem*> PageItem::itemsWeldedTo(PageItem* except) return ret; } +void PageItem::setWeldPoint(double DX, double DY, PageItem *pItem) +{ + for (int i = 0 ; i < weldList.count(); i++) + { + PageItem *pIt = weldList[i].weldItem; + if (pIt == pItem) + { + weldList[i].weldPoint = FPoint(DX, DY); + return; + } + } +} + void PageItem::unWeld() { + UndoTransaction* activeTransaction = NULL; + if (undoManager->undoEnabled()) + activeTransaction = new UndoTransaction(undoManager->beginTransaction(Um::WeldItems + "/" + Um::Selection, Um::IGroup, + Um::WeldItems, "", Um::IDelete)); for (int a = 0 ; a < weldList.count(); a++) { weldingInfo wInf = weldList.at(a); PageItem *pIt = wInf.weldItem; + if (pIt == NULL) + { + qDebug() << "unWeld - null pointer in weldList"; + continue; + } for (int b = 0 ; b < pIt->weldList.count(); b++) { weldingInfo wInf2 = pIt->weldList.at(b); @@ -10158,10 +10399,53 @@ void PageItem::unWeld() if (pIt2 == this) { pIt->weldList.removeAt(b); + if(undoManager->undoEnabled() && !(isAutoNoteFrame() || pIt->isAutoNoteFrame())) + { + ScItemState<PageItem*> *is = new ScItemState<PageItem*>(Um::WeldItems,"",Um::IGroup); + is->set("UNWELD_ITEM", "unweld_item"); + is->setItem(pIt); + is->set("thisPoint_x", wInf.weldPoint.x()); + is->set("thisPoint_y", wInf.weldPoint.y()); + is->set("thisID", wInf.weldID); + is->set("Point_x", wInf2.weldPoint.x()); + is->set("Point_y", wInf2.weldPoint.y()); + is->set("ID", wInf2.weldID); + undoManager->action(this, is, getUPixmap()); + } break; } } } + if (activeTransaction) + { + activeTransaction->commit(); + delete activeTransaction; + activeTransaction = NULL; + } weldList.clear(); } +QString PageItem::getItemTextSaxed(int selStart, int selLength) +{ + if (selStart < 0 || selLength < 0) + return QString(); + + StoryText it(m_Doc); + it.setDefaultStyle(itemText.defaultStyle()); + + if (selLength == 0) + selLength = 1; + itemText.deselectAll(); + itemText.select(selStart, selLength); + it.insert(0, itemText, true); + itemText.deselectAll(); + + //saxing text + std::ostringstream xmlString; + SaxXML xmlStream(xmlString); + xmlStream.beginDoc(); + it.saxx(xmlStream, "SCRIBUSTEXT"); + xmlStream.endDoc(); + std::string xml(xmlString.str()); + return QString(xml.c_str()); +} diff --git Scribus/scribus/pageitem.h Scribus/scribus/pageitem.h index 49f9c00..a454fb6 100644 --- Scribus/scribus/pageitem.h +++ Scribus/scribus/pageitem.h @@ -72,6 +72,7 @@ class PageItem_PolyLine; class PageItem_RegularPolygon; class PageItem_Table; class PageItem_TextFrame; +class PageItem_NoteFrame; class PageItem_PathText; class PageItem_LatexFrame; class PageItem_Spiral; @@ -99,6 +100,9 @@ class SCRIBUS_API PageItem : public QObject, public UndoObject, public SaxIO, pu Q_PROPERTY(double lineTransparency READ lineTransparency WRITE setLineTransparency DESIGNABLE false) Q_PROPERTY(bool m_Locked READ locked WRITE setLocked DESIGNABLE false) Q_PROPERTY(bool m_SizeLocked READ sizeLocked WRITE setSizeLocked DESIGNABLE false) + //used for notes frames + Q_PROPERTY(bool m_SizeHLocked READ sizeHLocked WRITE setSizeHLocked DESIGNABLE false) + Q_PROPERTY(bool m_SizeVLocked READ sizeVLocked WRITE setSizeVLocked DESIGNABLE false) Q_PROPERTY(bool m_ImageIsFlippedV READ imageFlippedV WRITE setImageFlippedV DESIGNABLE false) Q_PROPERTY(bool m_ImageIsFlippedH READ imageFlippedH WRITE setImageFlippedH DESIGNABLE false) Q_PROPERTY(double lineWidth READ lineWidth WRITE setLineWidth DESIGNABLE false) @@ -195,6 +199,7 @@ public: virtual PageItem_Polygon * asPolygon() { return NULL; } virtual PageItem_PolyLine * asPolyLine() { return NULL; } virtual PageItem_TextFrame * asTextFrame() { return NULL; } + virtual PageItem_NoteFrame * asNoteFrame() { return NULL; } virtual PageItem_LatexFrame * asLatexFrame() { return NULL; } virtual PageItem_OSGFrame * asOSGFrame() { return NULL; } @@ -219,6 +224,8 @@ public: virtual bool isArc() const { return false; } virtual bool isSpiral() const { return false; } virtual bool isTable() const { return false; } + virtual bool isNoteFrame() const { return false; } + virtual bool isAutoNoteFrame() const { return false; } /** @brief Frame Type * @@ -237,15 +244,7 @@ protected: public: PageItem(ScribusDoc *pa, ItemType newType, double x, double y, double w, double h, double w2, QString fill, QString outline); - ~PageItem() - { - if (tempImageFile != NULL) - delete tempImageFile; -// if (isWeld()) -// unWeldFromMaster(true); -// if (isWelded()) -// unWeldChild(); - } + ~PageItem(); // Get item level relative to its parent doc or group int level(); @@ -322,7 +321,8 @@ public: void SetFrameRound(); void setPolyClip(int up, int down = 0); void updatePolyClip(); - void updateClip(); + //added switch for not updating welded items - used by notes frames with automatic size adjusted + void updateClip(bool updateWelded = true); void convertClip(); void getBoundingRect(double *x1, double *y1, double *x2, double *y2) const; void getVisualBoundingRect(double *x1, double *y1, double *x2, double *y2) const; @@ -543,6 +543,9 @@ public: PageItem* nextInChain() { return NextBox; } const PageItem* prevInChain() const { return BackBox; } const PageItem* nextInChain() const { return NextBox; } + //you can change all code for search first or last item in chain + PageItem* firstInChain(); + PageItem* lastInChain(); PageItem *Parent; bool testLinkCandidate(PageItem* nextFrame); @@ -1110,8 +1113,12 @@ public: void toggleSizeLock(); /** @brief Is the item's size locked? */ bool sizeLocked() const { return m_SizeLocked; } + bool sizeHLocked() const { return m_SizeHLocked || m_SizeLocked; } + bool sizeVLocked() const { return m_SizeVLocked || m_SizeLocked; } /** @brief set lock for resizing */ void setSizeLocked(bool isLocked); + void setSizeHLocked(bool isLocked) { m_SizeHLocked = isLocked; } + void setSizeVLocked(bool isLocked) { m_SizeVLocked = isLocked; } /** * @brief Does text flow around this object and how @@ -1222,8 +1229,9 @@ public: * @author Craig Ringer * * Usually of the form 'Copy of [name]' or 'Copy of [name] (n)' + * cezaryece: if prependCopy is false then form '[name] (n)' is generated */ - QString generateUniqueCopyName(const QString originalName) const; + QString generateUniqueCopyName(const QString originalName, bool prependCopy = true) const; /** * @brief Is this item printed? * @sa setPrintEnabled() @@ -1416,6 +1424,8 @@ protected: void restoreCustomLineStyle(SimpleState *state, bool isUndo); void restoreArrow(SimpleState *state, bool isUndo, bool isStart); + void restorePStyle(SimpleState *state, bool isUndo); + void restoreType(SimpleState *state, bool isUndo); void restoreTextFlowing(SimpleState *state, bool isUndo); void restoreImageScaleMode(SimpleState *state, bool isUndo); @@ -1436,6 +1446,10 @@ protected: void restoreUnlinkTextFrame(UndoState *state, bool isUndo); void restoreReverseText(UndoState *state, bool isUndo); void restorePathOperation(UndoState *state, bool isUndo); + + void restoreWeldItems(SimpleState *state, bool isUndo); + void restoreUnWeldItem(SimpleState *state, bool isUndo); + /*@}*/ /** @@ -1567,6 +1581,11 @@ protected: bool m_SizeLocked; /** + * @for notes frames - locking horizontal or vertical size + **/ + bool m_SizeHLocked; + bool m_SizeVLocked; + /** * @brief Should text flow around the item * @sa PageItem::textFlowMode(), PateItem::setTextFlowMode() */ @@ -1781,6 +1800,11 @@ public: void moveWelded(double DX, double DY, int weld); void moveWelded(double DX, double DY, PageItem* except = NULL); void rotateWelded(double dR, double oldRot); + //added for autowelding feature of notes frames + //setting welding point with given pItem to given coords + void setWeldPoint(double DX, double DY, PageItem *pItem); + //used by notes frames to get content of notes from itemText + QString getItemTextSaxed(int selStart, int selLength); }; Q_DECLARE_METATYPE(PageItem*) diff --git Scribus/scribus/pageitem_noteframe.cpp Scribus/scribus/pageitem_noteframe.cpp new file mode 100644 index 0000000..adb1d8c --- /dev/null +++ Scribus/scribus/pageitem_noteframe.cpp @@ -0,0 +1,424 @@ +#include <QMessageBox> +#include "pageitem_noteframe.h" +#include "pageitem_textframe.h" +#include "pageitem.h" +#include "scribus.h" +#include "scribusdoc.h" +#include "ui/scmessagebox.h" +#include "undomanager.h" +#include "util_text.h" + +#include <cmath> + +PageItem_NoteFrame::PageItem_NoteFrame(NotesStyle *nStyle, ScribusDoc *doc, double x, double y, double w, double h, double w2, QString fill, QString outline) + : PageItem_TextFrame(doc, x, y, w, h, w2, fill, outline) +{ + m_nstyle = nStyle; + m_masterFrame = NULL; + itemText.clear(); + + AnName = generateUniqueCopyName(nStyle->isEndNotes() ? tr("Endnote frame ") + m_nstyle->name() : tr("Footnote frame ") + m_nstyle->name(), false); + AutoName = false; //endnotes frame will saved with name + setUName(AnName); + + //set default style for note frame + ParagraphStyle newStyle; + if (nStyle->notesParStyle().isEmpty() || (nStyle->notesParStyle() == tr("No Style"))) + { + if (nStyle->isEndNotes()) + //set default doc style + newStyle.setParent(m_Doc->paragraphStyles()[0].name()); + else + { + newStyle.setParent(m_masterFrame->itemText.defaultStyle().parent()); + newStyle.applyStyle(m_masterFrame->currentStyle()); + } + } + else + newStyle.setParent(nStyle->notesParStyle()); + itemText.blockSignals(true); + itemText.setDefaultStyle(newStyle); + itemText.blockSignals(false); + + textFlowModeVal = TextFlowUsesFrameShape; + setColumns(1); + + if (m_nstyle->isAutoNotesHeight()) + m_SizeVLocked = true; + else + m_SizeVLocked = false; + if (m_nstyle->isAutoNotesWidth()) + m_SizeHLocked = true; + else + m_SizeHLocked = false; + if (m_nstyle->isAutoNotesHeight() && m_nstyle->isAutoNotesWidth()) + m_SizeLocked = true; + else + m_SizeLocked = false; + deleteIt = false; + l_notes.empty(); +} + +PageItem_NoteFrame::PageItem_NoteFrame(ScribusDoc *doc, double x, double y, double w, double h, double w2, QString fill, QString outline) + : PageItem_TextFrame(doc, x, y, w, h, w2, fill, outline) +{ + m_nstyle = NULL; + m_masterFrame = NULL; + textFlowModeVal = TextFlowUsesFrameShape; + deleteIt = false; + l_notes.empty(); +} + +PageItem_NoteFrame::PageItem_NoteFrame(PageItem_TextFrame* inFrame, NotesStyle *nStyle) : PageItem_TextFrame(inFrame->doc(),inFrame->xPos(), inFrame->yPos(),inFrame->width(), inFrame->height(),inFrame->lineWidth(), inFrame->fillColor(), inFrame->lineColor()) +{ + m_nstyle = nStyle; + m_masterFrame = inFrame; + + AnName = generateUniqueCopyName(nStyle->isEndNotes() ? tr("Endnote frame ") + m_nstyle->name() : tr("Footnote frame ") + m_nstyle->name(), false); + AutoName = false; + setUName(AnName); + + //set default style for note frame + ParagraphStyle newStyle; + if (nStyle->notesParStyle().isEmpty() || (nStyle->notesParStyle() == tr("No Style"))) + { + if (nStyle->isEndNotes()) + //set default doc style + newStyle.setParent(m_Doc->paragraphStyles()[0].name()); + else + { + newStyle.setParent(m_masterFrame->itemText.defaultStyle().parent()); + newStyle.applyStyle(m_masterFrame->currentStyle()); + } + } + else + newStyle.setParent(nStyle->notesParStyle()); + itemText.blockSignals(true); + itemText.setDefaultStyle(newStyle); + itemText.blockSignals(false); + + double frameHeight = calculateLineSpacing(newStyle, this); + if (frameHeight == 0.0 && !m_nstyle->isAutoNotesHeight()) + frameHeight = newStyle.charStyle().fontSize()/10; + Height = oldHeight = frameHeight; + oldWidth = Width; + oldRot = Rot; + oldXpos = Xpos; + Ypos = oldYpos =m_masterFrame->yPos() + m_masterFrame->height(); + + textFlowModeVal = TextFlowUsesFrameShape; + setColumns(1); + + if (m_nstyle->isAutoWeldNotesFrames() && (m_masterFrame != NULL)) + { + addWelded(m_masterFrame); + m_masterFrame->addWelded(this); + m_masterFrame->setWeldPoint(0, m_masterFrame->height(), this); + setWeldPoint(0,0, m_masterFrame); + } + if (m_nstyle->isAutoNotesHeight()) + m_SizeVLocked = true; + else + m_SizeVLocked = false; + if (m_nstyle->isAutoNotesWidth()) + m_SizeHLocked = true; + else + m_SizeHLocked = false; + if (m_nstyle->isAutoNotesHeight() && m_nstyle->isAutoNotesWidth()) + m_SizeLocked = true; + else + m_SizeLocked = false; + deleteIt = false; + l_notes.empty(); +} + +void PageItem_NoteFrame::setNS(NotesStyle *nStyle, PageItem_TextFrame* master) +{ + m_nstyle = nStyle; + if (master != NULL) + m_masterFrame = master; + itemText.clear(); + + AnName = generateUniqueCopyName(m_nstyle->isEndNotes() ? "Endnote frame " + m_nstyle->name() : "Footnote frame " + m_nstyle->name(), false); + setUName(AnName); + + //set default style for note frame + ParagraphStyle newStyle; + if (nStyle->notesParStyle().isEmpty() || (nStyle->notesParStyle() == tr("No Style"))) + { + if (nStyle->isEndNotes() || (m_masterFrame == NULL)) + { + //set default doc style + newStyle.setParent(m_Doc->paragraphStyles()[0].name()); + } + else if (master != NULL) + { + newStyle.setParent(m_masterFrame->itemText.defaultStyle().parent()); + newStyle.applyStyle(m_masterFrame->currentStyle()); + } + } + else + newStyle.setParent(nStyle->notesParStyle()); + itemText.blockSignals(true); + itemText.setDefaultStyle(newStyle); + itemText.blockSignals(false); + + if (m_nstyle->isAutoNotesHeight()) + m_SizeVLocked = true; + else + m_SizeVLocked = false; + if (m_nstyle->isAutoNotesWidth()) + m_SizeHLocked = true; + else + m_SizeHLocked = false; + if (m_nstyle->isAutoNotesHeight() && m_nstyle->isAutoNotesWidth()) + m_SizeLocked = true; + else + m_SizeLocked = false; +} + +void PageItem_NoteFrame::layout() +{ + if (!invalid || l_notes.isEmpty()) + return; + if (!m_Doc->flag_layoutNotesFrames) + return; + if (itemText.length() == 0) + return; + if ((masterFrame() != NULL) && masterFrame()->invalid) + return; + + //while layouting notes frames undo should be disabled + UndoManager::instance()->setUndoEnabled(false); + + if (m_nstyle->isAutoNotesWidth() && (Width != m_masterFrame->width())) + { + oldWidth = Width = m_masterFrame->width(); + updateClip(); + } + + if ((m_Doc->appMode == modeEdit) && isSelected()) + updateNotesText(); + + PageItem_TextFrame::layout(); + int oldH = Height; + if (notesStyle()->isAutoNotesHeight()) + { + if (frameOverflows()) + { + //increase height while text don`t fit in frame + double maxH = m_Doc->currentPage()->height() - Xpos; + while (frameOverflows()) + { + oldHeight = Height += 8; + updateClip(false); + invalid = true; + PageItem_TextFrame::layout(); + if (Height >= maxH) + break; + } + } + double hackValue = 0.5; + oldHeight = Height = ceil(maxY) + BExtra + hackValue; + updateConstants(); + updateClip(); + invalid = true; + PageItem_TextFrame::layout(); + } + if (oldH != height()) + { + if (masterFrame() != NULL) + { + foreach(PageItem_NoteFrame* nF, masterFrame()->notesFramesList()) + nF->invalid = true; + } + } + invalid = false; + m_Doc->regionsChanged()->update(getBoundingRect()); + UndoManager::instance()->setUndoEnabled(true); +} + +void PageItem_NoteFrame::insertNote(TextNote *note) +{ + Mark* mrk = note->noteMark(); + if (mrk == NULL) + { + mrk = m_Doc->newMark(); + mrk->setType(MARKNoteFrameType); + QString label = "NoteFrameMark_" + notesStyle()->name(); + if (notesStyle()->range() == NSRsection) + label += " in section " + m_Doc->getSectionNameForPageIndex(note->masterMark()->OwnPage) + " page " + QString::number(note->masterMark()->OwnPage +1); + else if (notesStyle()->range() == NSRpage) + label += " on page " + QString::number(note->masterMark()->OwnPage +1); + else if (notesStyle()->range() == NSRstory) + label += " in " + note->masterMark()->getItemPtr()->firstInChain()->itemName(); + else if (notesStyle()->range() == NSRframe) + label += " in frame " + note->masterMark()->getItemName(); + mrk->label = label + "_" + note->numString(); + mrk->setNotePtr(note); + getUniqueName(mrk->label, m_Doc->marksLabelsList(MARKNoteFrameType), "_"); + note->setNoteMark(mrk); + } + mrk->setItemPtr(this); + mrk->setString(notesStyle()->prefix() + note->numString() + note->notesStyle()->suffix()); + + StoryText story; + if (!note->saxedText().isEmpty()) + story = desaxeString(m_Doc, note->saxedText()); + story.insertMark(mrk, 0); + story.setDefaultStyle(itemText.defaultStyle()); +// story.applyCharStyle(0, story.length(), itemText.charStyle()); + if (itemText.length() > 0) + itemText.insertChars(itemText.length(), SpecialChars::PARSEP); + itemText.insert(itemText.length(), story); +} + +void PageItem_NoteFrame::updateNotes(QList<TextNote*> nList, bool clear) +{ + if (nList == l_notes && !clear) + return; + UndoManager::instance()->setUndoEnabled(false); + m_Doc->setNotesChanged(true); + //itemText.blockSignals(true); + + if (clear) + { + itemText.selectAll(); + deleteSelectedTextFromFrame(); + l_notes = nList; + for (int a=0; a < l_notes.count(); ++a) + insertNote(l_notes.at(a)); + } + else + { + //just insert new notes into frame notes list + int count = nList.count(); + if (count > 0) + { + for (int i=0; i< count; ++i) + { + TextNote* note = nList.at(i); + if (!l_notes.contains(note)) + { + l_notes.append(note); + insertNote(note); + } + } + } + } + UndoManager::instance()->setUndoEnabled(true); + //itemText.blockSignals(false); + invalid = true; +} + +void PageItem_NoteFrame::updateNotesText() +{ + //read texts from notes frame and copy it to note`s data + if (l_notes.isEmpty() || (itemText.length() == 0)) + return; + + int oldSelStart = itemText.startOfSelection(); + int oldSelLen = itemText.lengthOfSelection(); + int pos = 0; + int startPos = 0; + TextNote *note = NULL; + Mark* prevMrk = NULL; + while (pos < itemText.length()) + { + ScText* hl = itemText.item(pos); + if (hl->hasMark() && hl->mark->isType(MARKNoteFrameType)) + { + if (prevMrk != NULL) + { + note = prevMrk->getNotePtr(); + if (note != NULL) + { + int offset = 0; + if (itemText.text(pos-1) == SpecialChars::PARSEP) + ++offset; + int len = pos - startPos -offset; + if (len <= 0) + note->setSaxedText(""); + else + note->setSaxedText(getItemTextSaxed(startPos, len)); + note->textLen = len; + itemText.deselectAll(); + } + } + prevMrk = hl->mark; + startPos = pos +1; + } + ++pos; + } + if (prevMrk != NULL) + { + note = prevMrk->getNotePtr(); + Q_ASSERT(note != NULL); + if (startPos != pos) + { + note->setSaxedText(getItemTextSaxed(startPos, pos - startPos)); + note->textLen = pos - startPos; + } + else //empty note text (only note marker) + { + note->setSaxedText(""); + note->textLen = 0; + } + } + if (oldSelLen > 0) + itemText.select(oldSelStart, oldSelLen); +} + +void PageItem_NoteFrame::restoreDeleteNoteText(SimpleState *state, bool isUndo) +{ + PageItem::restoreDeleteFrameText(state, isUndo); + updateNotesText(); +} + +void PageItem_NoteFrame::restoreInsertNoteText(SimpleState *state, bool isUndo) +{ + PageItem::restoreInsertFrameText(state, isUndo); + updateNotesText(); +} + +void PageItem_NoteFrame::unWeld(bool doUndo) +{ + if (doUndo) + PageItem::unWeld(); + else + { + for (int a = 0 ; a < weldList.count(); a++) + { + weldingInfo wInf = weldList.at(a); + PageItem *pIt = wInf.weldItem; + for (int b = 0 ; b < pIt->weldList.count(); b++) + { + weldingInfo wInf2 = pIt->weldList.at(b); + PageItem *pIt2 = wInf2.weldItem; + if (pIt2 == this) + { + pIt->weldList.removeAt(b); + break; + } + } + } + weldList.clear(); + } +} + +int PageItem_NoteFrame::findNoteCpos(TextNote* note) +{ + //find position of note in note`s frame + if (itemText.length() == 0) + return -1; + for (int pos=0; pos < itemText.length(); ++pos) + { + ScText* hl = itemText.item(pos); + if (hl->hasMark() && hl->mark->isType(MARKNoteFrameType)) + { + if (hl->mark->getNotePtr() == note) + return (pos); + } + } + return -1; +} diff --git Scribus/scribus/pageitem_noteframe.h Scribus/scribus/pageitem_noteframe.h new file mode 100644 index 0000000..7e44e49 --- /dev/null +++ Scribus/scribus/pageitem_noteframe.h @@ -0,0 +1,69 @@ +#ifndef PAGEITEM_NOTEFRAME_H +#define PAGEITEM_NOTEFRAME_H + +#include "pageitem_textframe.h" +#include "notesstyles.h" +#include "undostate.h" + +class PageItem_NoteFrame : public PageItem_TextFrame +{ + Q_OBJECT +friend class ScribusDoc; +private: + PageItem_NoteFrame(NotesStyle *nStyle, ScribusDoc *doc, double x, double y, double w, double h, double w2, QString fill, QString outline); + PageItem_NoteFrame(ScribusDoc *doc, double x, double y, double w, double h, double w2, QString fill, QString outline); + PageItem_NoteFrame(PageItem_TextFrame* inFrame, NotesStyle *nStyle); + ~PageItem_NoteFrame() { } +public: + virtual PageItem_NoteFrame * asNoteFrame() { return this; } + virtual bool isNoteFrame() const { return true; } + virtual bool isAutoNoteFrame() const { return m_nstyle->isAutoRemoveEmptyNotesFrames(); } + + //overloaded text frame layouting + void layout(); + + //indicate if noteframe should be deleted + bool deleteIt; + + //used while reading SLA file + void setNS(NotesStyle* nStyle, PageItem_TextFrame* master = NULL); + //returns Notes Style + NotesStyle* notesStyle() { return m_nstyle; } + + //insert notes content into notesframe + void updateNotes(QList<TextNote*> nList, bool clear = true); + //read notes text from notesframe itemText and store it in notes`s saxed text field + void updateNotesText(); + + PageItem_TextFrame* masterFrame() { return m_masterFrame; } + void setMaster(PageItem* frame) { m_masterFrame = frame->asTextFrame(); } + bool isEndNotesFrame() { return m_nstyle->isEndNotes(); } + bool isAutoWelded() { return m_nstyle->isAutoWeldNotesFrames(); } + bool isAutoHeight() { return m_nstyle->isAutoNotesHeight(); } + bool isAutoWidth() { return m_nstyle->isAutoNotesWidth(); } + + //return list of notes in noteframe + QList<TextNote*> notesList() { return l_notes; } + //remove note from list + void removeNote(TextNote* note) { l_notes.removeOne(note); } + + void restoreDeleteNoteText(SimpleState *state, bool isUndo); + void restoreInsertNoteText(SimpleState *state, bool isUndo); + //overloaded PageItem::unWeld() + void unWeld(bool doUndo=true); + +private: + QList<TextNote*> l_notes; + NotesStyle* m_nstyle; + PageItem_TextFrame *m_masterFrame; + + //insert note at end of text in noteframe + void insertNote(TextNote* note); + +//not used??? + //find position of note marker in text + int findNoteCpos(TextNote* note); + +}; + +#endif // PAGEITEM_NOTEFRAME_H diff --git Scribus/scribus/pageitem_textframe.cpp Scribus/scribus/pageitem_textframe.cpp index d18fb28..f6973a9 100644 --- Scribus/scribus/pageitem_textframe.cpp +++ Scribus/scribus/pageitem_textframe.cpp @@ -35,9 +35,12 @@ for which a new license (GPL+exception) is in place. #include "canvas.h" #include "commonstrings.h" #include "hyphenator.h" +#include "marks.h" +#include "notesstyles.h" #include "pageitem.h" #include "pageitem_group.h" #include "pageitem_textframe.h" +#include "pageitem_noteframe.h" #include "prefsmanager.h" #include "scpage.h" #include "scpainter.h" @@ -54,6 +57,8 @@ for which a new license (GPL+exception) is in place. #include "util_math.h" #include "ui/guidemanager.h" +//don`t worry - message boxes are called only if GUI is enabled +#include "ui/scmessagebox.h" #include <cairo.h> @@ -79,6 +84,7 @@ PageItem_TextFrame::PageItem_TextFrame(const PageItem & p) : PageItem(p) unicodeTextEditMode = false; unicodeInputCount = 0; unicodeInputString = ""; + m_notesFramesMap.clear(); connect(&itemText,SIGNAL(changed()), this, SLOT(slotInvalidateLayout())); } @@ -282,6 +288,8 @@ QRegion PageItem_TextFrame::calcAvailableRegion() } // for all docItems } // if(OnMasterPage.isEmpty() } // if(!Embedded) + else + qDebug() << "QRegion epmty"; return result; } @@ -317,7 +325,7 @@ void PageItem_TextFrame::setShadow() currentShadow = newShadow; } } - +/* static void debugLineLayout(const StoryText& itemText, const LineSpec& line) { QFile debugFile(QDir::homePath() + "/Desktop/debug_line.csv"); @@ -350,7 +358,7 @@ static void debugLineLayout(const StoryText& itemText, const LineSpec& line) debugFile.close(); } - +*/ static void dumpIt(const ParagraphStyle& pstyle, QString indent = QString("->")) { QString db = QString("%6%1/%2 @ %3: %4--%5 linespa%6: %7 align%8") @@ -1195,8 +1203,8 @@ static double nextAutoTab (const LineControl ¤t, PageItem *item) return res; } - -static double calculateLineSpacing (const ParagraphStyle &style, PageItem *item) +//cezaryece: I remove static statement as this function is used also by PageItem_NoteFrame +double calculateLineSpacing (const ParagraphStyle &style, PageItem *item) { if (style.lineSpacingMode() == ParagraphStyle::AutomaticLineSpacing) { @@ -1330,7 +1338,6 @@ void PageItem_TextFrame::layout() double EndX, OFs, wide, kernVal; QString chstr; ScText *hl; - PageItem_TextFrame* nextFrame; ParagraphStyle style; int opticalMargins = ParagraphStyle::OM_None; @@ -1378,6 +1385,8 @@ void PageItem_TextFrame::layout() //for moving next line if glyphs are higher than that double lastLineY = 0; + QMap<int, Mark*> noteMarksPosMap; //maping notes marks and its position in text + // dump styles /* for (int i=0; i < itemText.nrOfParagraphs(); ++i) { @@ -1390,7 +1399,33 @@ void PageItem_TextFrame::layout() */ setShadow(); - if ((itemText.length() != 0)) // || (NextBox != 0)) + int itLen = itemText.length(); + //fast validate empty frames + if (itLen == 0 || firstInFrame() == itLen) + { + PageItem* next = this; + while (next != NULL) + { + next->invalid = false; + next = next->nextInChain(); + } + if (!isNoteFrame() && m_Doc->notesChanged() && !m_notesFramesMap.isEmpty()) + { //if notes are used + UndoManager::instance()->setUndoEnabled(false); + QList<PageItem_NoteFrame*> delList; + foreach (PageItem_NoteFrame* nF, m_notesFramesMap.keys()) + { + if (nF->notesList().isEmpty() && !nF->isAutoNoteFrame()) + delList.append(nF); + } + while (!delList.isEmpty()) + m_Doc->delNoteFrame(delList.takeFirst(), false); + UndoManager::instance()->setUndoEnabled(true); + } + return; + } + + if ((itLen != 0)) // || (NextBox != 0)) { // determine layout area m_availableRegion = calcAvailableRegion(); @@ -1423,7 +1458,7 @@ void PageItem_TextFrame::layout() double autoLS = static_cast<double>(m_Doc->typographicPrefs().autoLineSpacing) / 100.0; // find start of first line - if (firstInFrame() < itemText.length()) + if (firstInFrame() < itLen) { hl = itemText.item(firstInFrame()); style = itemText.paragraphStyle(firstInFrame()); @@ -1464,27 +1499,92 @@ void PageItem_TextFrame::layout() current.mustLineEnd = current.colRight; current.restartX = 0; int lastStat = 0, curStat = 0; + + //why emit invalidating signals each time text is changed by appling styles? + //this speed up layouting in case of using notes marks and drop caps + itemText.blockSignals(true); setMaxY(-1); double maxYAsc = 0.0, maxYDesc = 0.0; - for (int a = firstInFrame(); a < itemText.length(); ++a) + for (int a = firstInFrame(); a < itLen; ++a) { hl = itemText.item(a); + bool HasObject = hl->hasObject(m_Doc); + bool HasMark = hl->hasMark(); + if (HasMark) + { + //show control characters for marks + hl->glyph.glyph = SpecialChars::OBJECT.unicode() + ScFace::CONTROL_GLYPHS; + + hl->mark->OwnPage = OwnPage; + //itemPtr and itemName set to this frame only if mark type is different than MARK2ItemType + if (!hl->mark->isType(MARK2ItemType)) + { + hl->mark->setItemPtr(this); + hl->mark->setItemName(itemName()); + } + //anchors and indexes has no visible inserts in text + if (hl->mark->isType(MARKAnchorType) || hl->mark->isType(MARKIndexType)) + { + hl->glyph.shrink(); + continue; + } + //store mark pointer and position in text + if (hl->mark->isType(MARKNoteMasterType)) + noteMarksPosMap.insert(a, hl->mark); + //set note marker charstyle + if (hl->mark->isNoteType()) + { + TextNote* note = hl->mark->getNotePtr(); + if (note == NULL) + continue; + hl->mark->setItemPtr(this); + NotesStyle* nStyle = note->notesStyle(); + Q_ASSERT(nStyle != NULL); + QString chsName = nStyle->marksChStyle(); + CharStyle newStyle(itemText.charStyle(a)); + if ((chsName != "") && (chsName != tr("No Style"))) + { + CharStyle marksStyle(m_Doc->charStyle(chsName)); + if (!newStyle.equiv(marksStyle)) + { + newStyle.setParent(chsName); + itemText.applyCharStyle(a, 1, marksStyle); + } + } + else + itemText.eraseCharStyle(a, 1, newStyle); + if (hl->mark->isType(MARKNoteMasterType)) + { + if (nStyle->isSuperscriptInMaster()) + hl->setEffects(hl->effects() | ScStyle_Superscript); + else + hl->setEffects(hl->effects() & ~ScStyle_Superscript); + } + else + { + if (nStyle->isSuperscriptInNote()) + hl->setEffects(hl->effects() | ScStyle_Superscript); + else + hl->setEffects(hl->effects() & ~ScStyle_Superscript); + } + } + } + chstr = ExpandToken(a); + int chstrLen = chstr.length(); + if (chstr.isEmpty()) + chstr = SpecialChars::ZWNBSPACE; + curStat = SpecialChars::getCJKAttr(hl->ch); if (a > 0 && itemText.text(a-1) == SpecialChars::PARSEP) style = itemText.paragraphStyle(a); if (current.itemsInLine == 0) opticalMargins = style.opticalMargins(); - CharStyle charStyle = (hl->ch != SpecialChars::PARSEP? itemText.charStyle(a) : style.charStyle()); - chstr = ExpandToken(a); double hlcsize10 = charStyle.fontSize() / 10.0; double scaleV = charStyle.scaleV() / 1000.0; double scaleH = charStyle.scaleH() / 1000.0; - offset = hlcsize10 * (charStyle.baselineOffset() / 1000.0); - - if (chstr.isEmpty()) - chstr = SpecialChars::ZWNBSPACE; + double offset = hlcsize10 * (charStyle.baselineOffset() / 1000.0); style.setLineSpacing (calculateLineSpacing (style, this)); FlopBaseline = (current.startOfCol && firstLineOffset() == FLOPBaselineGrid); @@ -1516,7 +1616,7 @@ void PageItem_TextFrame::layout() } else if (charStyle.name() != style.dcCharStyleName()) charStyle.setStyle(m_Doc->charStyle(style.dcCharStyleName())); - itemText.setCharStyle(a, chstr.length(),charStyle); + itemText.setCharStyle(a, chstrLen ,charStyle); } else if (style.dcCharStyleName() != tr("No Style") && !style.dcCharStyleName().isEmpty()) //hasDropCap is cleared but is set dcCharStyleName = clear drop cap char style @@ -1608,8 +1708,15 @@ void PageItem_TextFrame::layout() // FIXME : we should ensure that fonts are loaded before calls to layout() // ScFace::realCharHeight()/Ascent() ensure font is loaded thanks to an indirect call to char2CMap() // ScFace::ascent() can be called safely afterwards - double realCharHeight = font.realCharHeight(chstr[0], 1); - double realCharAscent = font.realCharAscent(chstr[0], 1); + + //text height, width, ascent and descent should be calculated for whole text provided by hl in current position + //and that may be more than one char (variable text for example) + double realCharHeight = 0.0, realCharAscent = 0.0; + for (int i = 0; i < chstrLen; ++i) + { + realCharHeight = qMax(realCharHeight, font.realCharHeight(chstr[i], 1)); + realCharAscent = qMax(realCharAscent, font.realCharAscent(chstr[i], 1)); + } double fontAscent = font.ascent(style.charStyle().fontSize() / 10.0); if (realCharHeight == 0.0) realCharHeight = font.height(style.charStyle().fontSize() / 10.0); @@ -1619,7 +1726,7 @@ void PageItem_TextFrame::layout() chs = (10 * ((DropCapDrop + fontAscent) / realCharAscent)); hl->setEffects(hl->effects() | ScStyle_DropCap); hl->glyph.yoffset -= DropCapDrop; - if ((hl->ch == SpecialChars::OBJECT) && (hl->hasObject(m_Doc))) + if (HasObject) { chs = qRound((hl->getItem(m_Doc)->height() + hl->getItem(m_Doc)->lineWidth()) * 10); chsd = qRound((hl->getItem(m_Doc)->height() + hl->getItem(m_Doc)->lineWidth()) * 10); @@ -1627,7 +1734,7 @@ void PageItem_TextFrame::layout() } else // ! dropCapMode { - if ((hl->ch == SpecialChars::OBJECT) && (hl->hasObject(m_Doc))) + if (HasObject) chs = qRound((hl->getItem(m_Doc)->height() + hl->getItem(m_Doc)->lineWidth()) * 10); else chs = charStyle.fontSize(); @@ -1646,7 +1753,7 @@ void PageItem_TextFrame::layout() hl->glyph.yadvance = 0; layoutGlyphs(*hl, chstr, hl->glyph); // find out width, ascent and descent of char - if ((hl->ch == SpecialChars::OBJECT) && (hl->hasObject(m_Doc))) + if (HasObject) { wide = hl->getItem(m_Doc)->width() + hl->getItem(m_Doc)->lineWidth(); hl->glyph.xadvance = wide * hl->glyph.scaleH; @@ -1742,7 +1849,7 @@ void PageItem_TextFrame::layout() if (DropCmode) { // drop caps are wider... - if ((hl->ch == SpecialChars::OBJECT) && (hl->hasObject(m_Doc))) + if (HasObject) { double itemHeight = hl->getItem(m_Doc)->height() + hl->getItem(m_Doc)->lineWidth(); if (itemHeight == 0) @@ -1756,11 +1863,19 @@ void PageItem_TextFrame::layout() } else { - double realCharHeight = font.realCharHeight(chstr[0], charStyle.fontSize() / 10.0); + double realCharHeight = 0.0; + wide = 0.0; realAsce = 0.0; + // + for (int i = 0; i < chstrLen; ++i) + { + realCharHeight = qMax(realCharHeight, font.realCharHeight(chstr[i], charStyle.fontSize() / 10.0)); + realAsce = qMax(realAsce, font.realCharHeight(chstr[i], chsd / 10.0)); + wide += font.realCharWidth(chstr[i], chsd / 10.0); + } + wide = (wide* scaleH) + (1 - scaleH); + realAsce = realAsce * scaleV + offset; if (realCharHeight == 0) realCharHeight = font.height(style.charStyle().fontSize() / 10.0); - wide = (font.realCharWidth(chstr[0], chsd / 10.0) * scaleH) + (1 - scaleH); //dropcaps are to close to next glyphs if glyphs are hard scaled - realAsce = font.realCharHeight(chstr[0], chsd / 10.0) * scaleV + offset; asce = font.ascent(hlcsize10); // qDebug() QString("dropcaps pre: chsd=%1 realCharHeight = %2 chstr=%3").arg(chsd).arg(asce).arg(chstr2[0]); hl->glyph.scaleH /= hl->glyph.scaleV; @@ -1780,15 +1895,22 @@ void PageItem_TextFrame::layout() wide *= wordtracking; } // find ascent / descent - if ((hl->ch == SpecialChars::OBJECT) && (hl->hasObject(m_Doc))) + if (HasObject) desc = realDesc = 0; else { + for (int i = 0; i < chstrLen; ++i) + { + if (chstr[i] == SpecialChars::OBJECT) + continue; + realDesc = qMax(realDesc, font.realCharDescent(chstr[i], hlcsize10)); + realAsce = font.realCharAscent(chstr[i], hlcsize10); + } + realDesc = realDesc * scaleV - offset; desc = -font.descent(hlcsize10); - realDesc = font.realCharDescent(chstr[0], hlcsize10) * scaleV - offset; current.rememberShrinkStretch(hl->ch, wide, style); } - if ((hl->ch == SpecialChars::OBJECT) && (hl->hasObject(m_Doc))) + if (HasObject) { asce = hl->getItem(m_Doc)->height() + hl->getItem(m_Doc)->lineWidth(); realAsce = asce * scaleV + offset; @@ -1796,7 +1918,13 @@ void PageItem_TextFrame::layout() else { asce = font.ascent(hlcsize10); - realAsce = font.realCharAscent(chstr[0], hlcsize10) * scaleV + offset; + if (HasMark) + realAsce = asce * scaleV + offset; + else + { + for (int i = 0; i < chstrLen; ++i) + realAsce = qMax(realAsce, font.realCharAscent(chstr[i], hlcsize10) * scaleV + offset); + } } } @@ -1809,6 +1937,9 @@ void PageItem_TextFrame::layout() if (current.startOfCol) { lastLineY = qMax(lastLineY, extra.Top + lineCorr); + //fix for proper rendering first empty line (only with PARSEP) + if (chstr[0] == SpecialChars::PARSEP) + current.yPos += style.lineSpacing(); if (style.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing || FlopBaseline) { if (current.yPos <= lastLineY) @@ -2021,14 +2152,14 @@ void PageItem_TextFrame::layout() diff = realAsce - (current.yPos - lastLineY); else if (style.lineSpacingMode() != ParagraphStyle::FixedLineSpacing) { - if ((hl->ch == SpecialChars::OBJECT) && (hl->hasObject(m_Doc))) + if (HasObject) diff = (hl->getItem(m_Doc)->height() + hl->getItem(m_Doc)->lineWidth()) * scaleV + offset - (current.yPos - lastLineY); else diff = font.realCharAscent(QChar('l'), hlcsize10) * scaleV + offset - (current.yPos - lastLineY); } else { - if ((hl->ch == SpecialChars::OBJECT) && (hl->hasObject(m_Doc))) + if (HasObject) diff = (hl->getItem(m_Doc)->height() + hl->getItem(m_Doc)->lineWidth()) * scaleV + offset - (current.yPos - lastLineY); } if (diff >= 1 || (!DropCmode && diff > 0)) @@ -2141,8 +2272,12 @@ void PageItem_TextFrame::layout() // remember y pos if (DropCmode) - hl->glyph.yoffset -= font.realCharHeight(chstr[0], chsd / 10.0) - font.realCharAscent(chstr[0], chsd / 10.0); - + { + double yoffset = 0.0; + for (int i = 0; i < chstrLen; ++i) + yoffset = qMax(yoffset, font.realCharHeight(chstr[i], chsd / 10.0) - font.realCharAscent(chstr[i], chsd / 10.0)); + hl->glyph.yoffset -= yoffset; + } // remember x pos double breakPos = current.xPos; @@ -2662,6 +2797,7 @@ void PageItem_TextFrame::layout() maxDX = 0; } } + lastLineY = current.rowDesc; current.mustLineEnd = current.colRight; current.restartRowIndex = current.restartIndex; } @@ -2811,20 +2947,31 @@ void PageItem_TextFrame::layout() if (moveLinesFromPreviousFrame ()) { layout (); // line moving ensures that this won't be an endless loop + itemText.blockSignals(false); return; } } } MaxChars = itemText.length(); invalid = false; - - nextFrame = dynamic_cast<PageItem_TextFrame*>(NextBox); - while (nextFrame != NULL) + if (!isNoteFrame() && (!m_Doc->notesList().isEmpty() || m_Doc->notesChanged())) + { //if notes are used + UndoManager::instance()->setUndoEnabled(false); + NotesInFrameMap notesMap = updateNotesFrames(noteMarksPosMap); + if (notesMap != m_notesFramesMap) + { + updateNotesMarks(notesMap); + notesFramesLayout(); + } + UndoManager::instance()->setUndoEnabled(true); + } + if (NextBox != NULL) { + PageItem_TextFrame * nextFrame = dynamic_cast<PageItem_TextFrame*>(NextBox); nextFrame->invalid = true; nextFrame->firstChar = MaxChars; - nextFrame = dynamic_cast<PageItem_TextFrame*>(nextFrame->NextBox); } + itemText.blockSignals(false); // qDebug("textframe: len=%d, done relayout", itemText.length()); return; @@ -2833,6 +2980,18 @@ NoRoom: adjustParagraphEndings (); + if (!isNoteFrame() && (!m_Doc->notesList().isEmpty() || m_Doc->notesChanged())) + { + UndoManager::instance()->setUndoEnabled(false); + NotesInFrameMap notesMap = updateNotesFrames(noteMarksPosMap); + if (notesMap != m_notesFramesMap) + { + updateNotesMarks(notesMap); + notesFramesLayout(); + } + UndoManager::instance()->setUndoEnabled(true); + } + PageItem_TextFrame * next = dynamic_cast<PageItem_TextFrame*>(NextBox); if (next != NULL) { @@ -2857,12 +3016,13 @@ NoRoom: next->layout(); } // qDebug("textframe: len=%d, done relayout (no room %d)", itemText.length(), MaxChars); + itemText.blockSignals(false); } -void PageItem_TextFrame::invalidateLayout() +void PageItem_TextFrame::invalidateLayout(bool wholeChain) { - const bool wholeChain = true; - this->invalid = true; + //const bool wholeChain = true; + invalid = true; if (wholeChain) { PageItem *prevFrame = this->prevInChain(); @@ -2880,10 +3040,37 @@ void PageItem_TextFrame::invalidateLayout() } } +void PageItem_TextFrame::slotInvalidateLayout() +{ + invalidateLayout(true); +} + +bool PageItem_TextFrame::isValidChainFromBegin() +{ + if (invalid) + return false; + if (BackBox == NULL) + return !invalid; + + PageItem* prev = prevInChain(); + while (prev != NULL) + { + if (prev->invalid) + return false; + prev = prev->prevInChain(); + } + return true; +} + void PageItem_TextFrame::DrawObj_Item(ScPainter *p, QRectF cullingArea) { if(invalid) + { + if (isNoteFrame() && asNoteFrame()->deleteIt) + //do not layout notes frames which should be deleted + return; layout(); + } if (invalid) return; QTransform pf2; @@ -2998,15 +3185,19 @@ void PageItem_TextFrame::DrawObj_Item(ScPainter *p, QRectF cullingArea) bool previousWasObject(false); double selX = ls.x; ScText *hls = 0; - for (int as = ls.firstItem; as <= qMin(ls.lastItem, itemText.length() - 1); ++as) + int last = qMin(ls.lastItem, itemText.length() - 1); + for (int as = ls.firstItem; as <= last; ++as) { bool selecteds = itemText.selected(as); hls = itemText.item(as); + bool HasObject = hls->hasObject(m_Doc); + if (hls->mark != NULL && (hls->mark->isType(MARKAnchorType) || hls->mark->isType(MARKIndexType))) + continue; if(selecteds) { const CharStyle& charStyleS(itemText.charStyle(as)); if(((as > ls.firstItem) && (charStyleS != itemText.charStyle(as-1))) - || ((!selectedFrame.isNull()) && (hls->ch == SpecialChars::OBJECT)) + || ((!selectedFrame.isNull()) && HasObject) || previousWasObject) { sFList << selectedFrame; @@ -3035,7 +3226,7 @@ void PageItem_TextFrame::DrawObj_Item(ScPainter *p, QRectF cullingArea) asce = font.ascent(fontSize); wide = hls->glyph.wide(); QRectF scr; - if ((hls->ch == SpecialChars::OBJECT) && (hls->hasObject(m_Doc))) + if (HasObject) { double ww = (hls->getItem(m_Doc)->width() + hls->getItem(m_Doc)->lineWidth()) * hls->glyph.scaleH; double hh = (hls->getItem(m_Doc)->height() + hls->getItem(m_Doc)->lineWidth()) * hls->glyph.scaleV; @@ -3071,7 +3262,7 @@ void PageItem_TextFrame::DrawObj_Item(ScPainter *p, QRectF cullingArea) QColor tmp; ScText *hl = 0; - for (int a = ls.firstItem; a <= qMin(ls.lastItem, itemText.length() - 1); ++a) + for (int a = ls.firstItem; a <= last; ++a) { hl = itemText.item(a); const CharStyle& charStyle(itemText.charStyle(a)); @@ -3128,10 +3319,19 @@ void PageItem_TextFrame::DrawObj_Item(ScPainter *p, QRectF cullingArea) { p->save();//SA4 p->translate(CurX, ls.y); - if ((hl->ch == SpecialChars::OBJECT) && (hl->hasObject(m_Doc))) + if (hl->hasObject(m_Doc)) DrawObj_Embedded(p, cullingArea, charStyle, hl->getItem(m_Doc)); else + { + //control chars for marks + if (m_Doc->guidesPrefs().showControls && hl->hasMark() && (hl->glyph.glyph != SpecialChars::OBJECT)) + { + GlyphLayout markGlyph; + layoutGlyphs(charStyle,SpecialChars::OBJECT, markGlyph); + drawGlyphs(p, charStyle, markGlyph); + } drawGlyphs(p, charStyle, hl->glyph); + } p->restore();//RE4 } // Unneeded now that glyph xadvance is set appropriately for inline objects by layout() - JG @@ -3313,7 +3513,7 @@ void PageItem_TextFrame::DrawObj_Decoration(ScPainter *p) //Draw the overflow icon if (frameOverflows()) { - if ((!m_Doc->drawAsPreview)) + if (!m_Doc->drawAsPreview) drawOverflowMarker(p); } if ((m_Doc->guidesPrefs().colBordersShown) && (!m_Doc->drawAsPreview)) @@ -3348,9 +3548,12 @@ void PageItem_TextFrame::clearContents() ParagraphStyle defaultStyle = nextItem->itemText.defaultStyle(); nextItem->itemText.selectAll(); nextItem->asTextFrame()->deleteSelectedTextFromFrame(); + if (!isNoteFrame()) + { if(UndoManager::undoEnabled()) undoManager->getLastUndo()->setName(Um::ClearText); nextItem->itemText.setDefaultStyle(defaultStyle); + } while (nextItem != 0) { @@ -3503,8 +3706,13 @@ void PageItem_TextFrame::handleModeEditKey(QKeyEvent *k, bool& keyRepeat) } // Tinput = true; m_Doc->scMW()->setTBvals(this); + if (isAutoNoteFrame() && m_Doc->notesChanged()) + { + Q_ASSERT(asNoteFrame()->masterFrame()); + asNoteFrame()->masterFrame()->invalid = true; + } + else update(); - doc()->changed(); keyRepeat = false; return; } @@ -3793,6 +4001,15 @@ void PageItem_TextFrame::handleModeEditKey(QKeyEvent *k, bool& keyRepeat) { deleteSelectedTextFromFrame(); m_Doc->scMW()->setTBvals(this); + if (isAutoNoteFrame() && asNoteFrame()->notesList().isEmpty()) + { + if (!asNoteFrame()->isEndNotesFrame()) + { + Q_ASSERT(asNoteFrame()->masterFrame()); + asNoteFrame()->masterFrame()->invalid = true; + } + } + else update(); // view->RefreshItem(this); } @@ -3808,10 +4025,20 @@ void PageItem_TextFrame::handleModeEditKey(QKeyEvent *k, bool& keyRepeat) if (itemText.lengthOfSelection() == 0) itemText.select(itemText.cursorPosition(), 1, true); deleteSelectedTextFromFrame(); - updateLayout(); + if (isAutoNoteFrame() && asNoteFrame()->notesList().isEmpty()) + { + if (!asNoteFrame()->isEndNotesFrame()) + { + Q_ASSERT(asNoteFrame()->masterFrame()); + asNoteFrame()->masterFrame()->invalid = true; + } + } + else + { + layout(); if (oldLast != lastInFrame() && NextBox != 0 && NextBox->invalid) NextBox->updateLayout(); - update(); + } // Tinput = false; // if ((cr == QChar(13)) && (itemText.length() != 0)) // { @@ -3819,7 +4046,6 @@ void PageItem_TextFrame::handleModeEditKey(QKeyEvent *k, bool& keyRepeat) // Tinput = false; // } m_Doc->scMW()->setTBvals(this); - doc()->changed(); // view->RefreshItem(this); break; case Qt::Key_Backspace: @@ -3829,6 +4055,15 @@ void PageItem_TextFrame::handleModeEditKey(QKeyEvent *k, bool& keyRepeat) { deleteSelectedTextFromFrame(); m_Doc->scMW()->setTBvals(this); + if (isAutoNoteFrame() && asNoteFrame()->notesList().isEmpty()) + { + if (!asNoteFrame()->isEndNotesFrame()) + { + Q_ASSERT(asNoteFrame()->masterFrame()); + asNoteFrame()->masterFrame()->invalid = true; + } + } + else update(); } break; @@ -3843,14 +4078,25 @@ void PageItem_TextFrame::handleModeEditKey(QKeyEvent *k, bool& keyRepeat) } deleteSelectedTextFromFrame(); // Tinput = false; - if ((cr == QChar(13)) && (itemText.length() != 0)) - { +// if ((cr == QChar(13)) && (itemText.length() != 0)) +// { // m_Doc->chAbStyle(this, findParagraphStyle(m_Doc, itemText.paragraphStyle(qMax(CPos-1,0)))); // Tinput = false; +// } + if (isAutoNoteFrame() && asNoteFrame()->notesList().isEmpty()) + { + if (!asNoteFrame()->isEndNotesFrame()) + { + Q_ASSERT(asNoteFrame()->masterFrame()); + asNoteFrame()->masterFrame()->invalid = true; + } } - updateLayout(); + else + { + layout(); if (oldLast != lastInFrame() && NextBox != 0 && NextBox->invalid) NextBox->updateLayout(); + } if (itemText.cursorPosition() < firstInFrame()) { itemText.setCursorPosition( firstInFrame() ); @@ -3865,11 +4111,12 @@ void PageItem_TextFrame::handleModeEditKey(QKeyEvent *k, bool& keyRepeat) } } m_Doc->scMW()->setTBvals(this); - update(); - doc()->changed(); +// update(); // view->RefreshItem(this); break; default: + if (isNoteFrame() && itemText.cursorPosition() == 0) + break; //avoid inserting chars before first note mark bool doUpdate = false; UndoTransaction* activeTransaction = NULL; if (itemText.lengthOfSelection() > 0) //(kk < 0x1000) @@ -3917,7 +4164,13 @@ void PageItem_TextFrame::handleModeEditKey(QKeyEvent *k, bool& keyRepeat) ss->set("ETEA", QString("insert_frametext")); ss->set("TEXT_STR", QString(SpecialChars::TAB)); ss->set("START", itemText.cursorPosition()); - undoManager->action(this, ss); + UndoObject * undoTarget = this; + if (isNoteFrame()) + { + undoTarget = m_Doc; + ss->set("noteframeName", getUName()); + } + undoManager->action(undoTarget, ss); } } itemText.insertChars(QString(SpecialChars::TAB), true); @@ -3938,7 +4191,12 @@ void PageItem_TextFrame::handleModeEditKey(QKeyEvent *k, bool& keyRepeat) ss->set("ETEA", QString("insert_frametext")); ss->set("TEXT_STR",uc); ss->set("START", itemText.cursorPosition()); - undoManager->action(this, ss); + UndoObject * undoTarget = this; + if (isNoteFrame()) + { undoTarget = m_Doc; + ss->set("noteframeName", getUName()); + } + undoManager->action(undoTarget, ss); } } itemText.insertChars(uc, true); @@ -3976,12 +4234,21 @@ void PageItem_TextFrame::handleModeEditKey(QKeyEvent *k, bool& keyRepeat) } // update layout immediately, we need MaxChars to be correct to detect // if we need to move to next frame or not - updateLayout(); + if (isAutoNoteFrame() && asNoteFrame()->notesList().isEmpty()) + { + if (!asNoteFrame()->isEndNotesFrame()) + { + Q_ASSERT(asNoteFrame()->masterFrame()); + asNoteFrame()->masterFrame()->invalid = true; + } + } + else + update(); if (oldLast != lastInFrame() && NextBox != 0 && NextBox->invalid) NextBox->updateLayout(); - doc()->changed(); } //check if cursor need to jump to next linked frame + //but not for notes frames can`t be updated as may disapper during update if ((itemText.cursorPosition() > lastInFrame() + 1) && (lastInFrame() < (itemText.length() - 2)) && NextBox != 0) { view->Deselect(true); @@ -3996,12 +4263,17 @@ void PageItem_TextFrame::handleModeEditKey(QKeyEvent *k, bool& keyRepeat) keyRepeat = false; } -void PageItem_TextFrame::deleteSelectedTextFromFrame() +void PageItem_TextFrame::deleteSelectedTextFromFrame(/*bool findNotes*/) { - if (itemText.lengthOfSelection() > 0) { - if(UndoManager::undoEnabled()){ + if (itemText.lengthOfSelection() == 0) + { + itemText.select(itemText.cursorPosition(),1); + HasSel = true; + } int start = itemText.startOfSelection(); int stop = itemText.endOfSelection(); + int marksNum = 0; + if(UndoManager::undoEnabled()) { int lastPos = start; CharStyle lastParent = itemText.charStyle(start); UndoState* state = undoManager->getLastUndo(); @@ -4014,13 +4286,38 @@ void PageItem_TextFrame::deleteSelectedTextFromFrame() is = dynamic_cast<ScItemState<CharStyle>*>(ts->at(ts->sizet()-1)); state = ts->at(0); } - UndoTransaction trans = undoManager->beginTransaction(Um::Selection,Um::IDelete,Um::Delete,"",Um::IDelete); + UndoTransaction* trans = new UndoTransaction(undoManager->beginTransaction(Um::Selection,Um::IDelete,Um::Delete,"",Um::IDelete)); + + //find and delete notes and marks in selected text + QList<QPair<TextNote*, int> > notes2DEL; + if (isNoteFrame()/* && findNotes*/) + { + //find and delete notes + //if marks are in notes then they will be deleted further while note is physicaly deleted + for (int i=start; i < stop; ++i) + { + if (i == itemText.length()) + break; + ScText* hl = itemText.item(i); + if (hl->hasMark() && hl->mark->isType(MARKNoteFrameType)) + notes2DEL.append(QPair<TextNote*, int>(hl->mark->getNotePtr(), i)); + } + } + else + { + //delete marks from selected text (with undo) + marksNum = removeMarksFromText(true); + stop -= marksNum; + } + //delete text for (int i=start; i <= stop; ++i) { - const CharStyle& curParent(itemText.charStyle(i)); - if (curParent.equiv(lastParent) && i != stop) - continue; - + ScText* hl = NULL; + if (i < itemText.length()) + hl = itemText.item(i); + const CharStyle& curParent = itemText.charStyle(i); + if (i==stop || !curParent.equiv(lastParent) || (hl!=NULL && hl->hasMark() && hl->mark->isType(MARKNoteFrameType))) + { added = false; lastIsDelete = false; if (is && ts && dynamic_cast<ScItemState<CharStyle>*>(ts->at(0))->get("ETEA") == "delete_frametext" && lastPos<is->getInt("START")) @@ -4043,28 +4340,84 @@ void PageItem_TextFrame::deleteSelectedTextFromFrame() } if (!added) { + UndoObject * undoTarget = this; + is = NULL; + if (i - lastPos > 0) + { is = new ScItemState<CharStyle>(Um::DeleteText,"",Um::IDelete); is->set("DELETE_FRAMETEXT", "delete_frametext"); is->set("ETEA", QString("delete_frametext")); is->set("TEXT_STR",itemText.text(lastPos,i - lastPos)); is->set("START", start); is->setItem(lastParent); + } + //delete selected notes from notes frame + if (isNoteFrame()) + { + undoTarget = m_Doc; //undo target is doc for notes as after deleting last note notesframe can be deleted + if (is) + is->set("noteframeName", getUName()); + //remove marks from notes + for (int ii = notes2DEL.count() -1; ii >= 0; --ii) + { + TextNote* note = notes2DEL.at(ii).first; + Q_ASSERT(note != NULL); + if (note->textLen > 0) + { + itemText.deselectAll(); + itemText.select(notes2DEL.at(ii).second + 1, note->textLen); + removeMarksFromText(true); + } + } + asNoteFrame()->updateNotesText(); + for (int ii = notes2DEL.count() -1; ii >= 0; --ii) + { + TextNote* note = notes2DEL.at(ii).first; + Q_ASSERT(note != NULL); + m_Doc->setUndoDelNote(note); + if (note->isEndNote()) + m_Doc->flag_updateEndNotes = true; + m_Doc->deleteNote(note); + } + if(is) + { + if (!ts || !lastIsDelete){ + undoManager->action(undoTarget, is); + ts = NULL; + } + else + ts->pushBack(undoTarget,is); + } + break; + } + if (is) + { if(!ts || !lastIsDelete){ - undoManager->action(this, is); + undoManager->action(undoTarget, is); ts = NULL; } else - ts->pushBack(this,is); + ts->pushBack(undoTarget,is); + } } lastPos = i; lastParent = curParent; } - trans.commit(); } - itemText.setCursorPosition( itemText.startOfSelection() ); + if (trans) + { + trans->commit(); + delete trans; + trans = NULL; + } + } + else //remove marks without undo + marksNum =removeMarksFromText(false); + itemText.setCursorPosition( start ); + //for sure text is still selected + itemText.select(start, stop - start - marksNum); itemText.removeSelection(); HasSel = false; - } // m_Doc->updateFrameItems(); m_Doc->scMW()->DisableTxEdit(); } @@ -4362,8 +4715,39 @@ bool PageItem_TextFrame::createInfoGroup(QFrame *infoGroup, QGridLayout *infoGro return true; } +void PageItem_TextFrame::togleEditModeActions() +{ + bool editMode = (m_Doc->appMode == modeEdit); + bool masterMode = m_Doc->masterPageMode(); + m_Doc->scMW()->scrActions["insertMarkVariableText"]->setEnabled(editMode); + m_Doc->scMW()->scrActions["insertMarkAnchor"]->setEnabled(editMode && !masterMode); + m_Doc->scMW()->scrActions["insertMarkItem"]->setEnabled(editMode && !masterMode); + m_Doc->scMW()->scrActions["insertMark2Mark"]->setEnabled(editMode && !masterMode); + m_Doc->scMW()->scrActions["insertMarkNote"]->setEnabled(editMode && !masterMode && !isNoteFrame()); + // scrActions["insertMarkIndex"]->setEnabled(editMode && !masterMode); + bool enableEditMark = false; + if (editMode && (itemText.cursorPosition() < itemText.length())) + { + ScText *hl = itemText.item(itemText.cursorPosition()); + if (hl->hasMark()) + { + Mark* mrk = hl->mark; + //notes marks in note frames are not editable + if (!mrk->isType(MARKNoteFrameType)) + enableEditMark = true; + } + } + m_Doc->scMW()->scrActions["editMark"]->setEnabled(enableEditMark); +} + void PageItem_TextFrame::applicableActions(QStringList & actionList) { + actionList << "insertMarkVariableText"; + if (!m_Doc->masterPageMode()) + actionList << "insertMarkAnchor"; + //notes frames are not simply text frames + if (isNoteFrame()) + return; actionList << "fileImportText"; actionList << "fileImportAppendText"; actionList << "toolsEditWithStoryEditor"; @@ -4396,9 +4780,422 @@ QString PageItem_TextFrame::infoDescription() return QString(); } -void PageItem_TextFrame::slotInvalidateLayout() +bool PageItem_TextFrame::hasMark(NotesStyle *NS) +{ + if (isNoteFrame()) + return (asNoteFrame()->notesStyle() == NS); + + if (NS == NULL) + { + //find any mark + if (!m_notesFramesMap.isEmpty()) + return true; + for (int i=firstInFrame(); i <= lastInFrame(); ++i) + if (itemText.item(i)->hasMark()) + return true; + } + else + { + for (int pos = firstInFrame(); pos <= lastInFrame(); ++pos) + { + ScText* hl = itemText.item(pos); + if (hl->hasMark()) + { + TextNote* note = hl->mark->getNotePtr(); + if (note != NULL && (note->notesStyle() == NS)) + return true; + } + } + } + return false; +} + +bool PageItem_TextFrame::hasNoteFrame(NotesStyle *NS, bool inChain) +{ + if (isNoteFrame()) + return false; + if (m_notesFramesMap.isEmpty()) + return false; + if (NS == NULL) + { //check if any notes are in frame or whole chain + if (!inChain) + return !m_notesFramesMap.isEmpty(); + else + { + PageItem* item = this; + item = firstInChain(); + while (item != NULL) + { + if (item->asTextFrame()->hasNoteFrame(NULL, false)) + return true; + item = item->nextInChain(); + } + return false; + } + } + PageItem* item = this; + if (inChain) + item = firstInChain(); + while (item != NULL) + { + QMap<PageItem_NoteFrame*, QList<TextNote*> >::iterator it = m_notesFramesMap.begin(); + QMap<PageItem_NoteFrame*, QList<TextNote*> >::iterator end = m_notesFramesMap.end(); + while (it != end) + { + if (it.key()->notesStyle() == NS) + return true; + ++it; + } + if (!inChain) + break; + item = item->nextInChain(); + } + return false; +} + +void PageItem_TextFrame::delAllNoteFrames(bool doUpdate) +{ + int oldItemsCount = m_Doc->Items->count(); + + QList<PageItem_NoteFrame*> delList; + foreach (PageItem_NoteFrame* nF, m_notesFramesMap.keys()) + { + if (nF->notesList().isEmpty() && !nF->isAutoNoteFrame()) + delList.append(nF); + } + while (!delList.isEmpty()) + { + PageItem_NoteFrame* nF = delList.takeFirst(); + m_Doc->delNoteFrame(nF); + } + + //check if doc need update + if (doUpdate && (oldItemsCount != m_Doc->Items->count())) + { + m_Doc->changed(); + m_Doc->regionsChanged()->update(QRectF()); + } + m_Doc->setNotesChanged(true); +} + +Mark* PageItem_TextFrame::selectedMark(bool onlySelection) +{ //return pointer to first mark in selected (or whole) text + + bool omitNotes = true; //do not return notes marks (for searching notes use selectedNotesMark() + int start = 0; + int stop = 0; + if (onlySelection) + { + if (itemText.lengthOfSelection() > 0) + { + //only selection + start = itemText.startOfSelection(); + stop = start + itemText.lengthOfSelection(); + } + else //in edit mode only one char in cursor position + { + if (m_Doc->appMode == modeEdit) + { + //only char after cursor + start = itemText.cursorPosition(); + stop = start + 1; + if (stop > itemText.length()) + return NULL; + } + else + { + //only frame + start = firstInFrame(); + stop = lastInFrame(); + if (start == stop) + return NULL; + } + } + + } + else //in whole text + stop = itemText.length(); + + for (int pos = start; pos < stop; ++pos) + { + ScText* hl = itemText.item(pos); + if (hl->hasMark()) + { + if (omitNotes && (hl->mark->isType(MARKNoteMasterType) || hl->mark->isType(MARKNoteFrameType))) + continue; + return hl->mark; + } + } + return NULL; +} + +TextNote* PageItem_TextFrame::selectedNoteMark(ScText* &hl, bool onlySelection) +{ + //return pointer to note from first mark found in text + int start = 0; + int stop = itemText.length(); + if (onlySelection) + { + if (itemText.lengthOfSelection() > 0) + { + start = itemText.startOfSelection(); + stop = start + itemText.lengthOfSelection(); + } + else + return NULL; + } + MarkType typ = isNoteFrame()? MARKNoteFrameType : MARKNoteMasterType; + for (int pos = start; pos < stop; ++pos) + { + ScText* hl = itemText.item(pos); + if (hl->hasMark() && hl->mark->isType(typ)) + return hl->mark->getNotePtr(); + } + return NULL; +} + +TextNote* PageItem_TextFrame::selectedNoteMark(bool onlySelection) +{ + ScText* hl = NULL; + return selectedNoteMark(hl, onlySelection); +} + +NotesInFrameMap PageItem_TextFrame::updateNotesFrames(QMap<int, Mark*> noteMarksPosMap) +{ + NotesInFrameMap notesMap; //= m_notesFramesMap; + QMap<int, Mark*>::Iterator it = noteMarksPosMap.begin(); + QMap<int, Mark*>::Iterator end = noteMarksPosMap.end(); + PageItem* lastItem = this; + while (it != end) + { + if (it.key() <= lastInFrame()) + { + Mark* mark = it.value(); + mark->setItemPtr(this); + mark->setItemName(itemName()); + + TextNote* note = mark->getNotePtr(); + Q_ASSERT(note != NULL); + if (note == NULL) + { + qWarning() << "note mark without valid note pointer"; + note = m_Doc->newNote(m_Doc->m_docNotesStylesList.at(0)); + note->setMasterMark(mark); + mark->setNotePtr(note); + } + NotesStyle* NS = note->notesStyle(); + PageItem_NoteFrame* nF = NULL; + if (NS->isEndNotes()) + nF = m_Doc->endNoteFrame(NS, this); + else + nF = itemNoteFrame(NS); + if (nF == NULL) + { + //creating new noteframe + if (NS->isEndNotes()) + { + //create new endnotes frame + double x,y,w,h; + const ScPage* scP = m_Doc->page4EndNotes(NS, this); + x = scP->Margins.Left + m_Doc->rulerXoffset + scP->xOffset(); + y = scP->Margins.Top + m_Doc->rulerYoffset + scP->yOffset(); + w = scP->width() - scP->Margins.Left - scP->Margins.Right; + h = calculateLineSpacing(itemText.defaultStyle(), this); + nF = m_Doc->createNoteFrame(note->notesStyle(), x, y, w, h, m_Doc->itemToolPrefs().shapeLineWidth, CommonStrings::None, m_Doc->itemToolPrefs().textFont); + switch (NS->range()) + { //insert pointer to endnoteframe into m_Doc->m_endNotesFramesMap + case NSRdocument: + m_Doc->setEndNoteFrame(nF, (void*) NULL); + break; + case NSRsection: + m_Doc->setEndNoteFrame(nF, m_Doc->getSectionKeyForPageIndex(OwnPage)); + case NSRstory: + m_Doc->setEndNoteFrame(nF, (void*) firstInChain()); + break; + case NSRpage: + m_Doc->setEndNoteFrame(nF, (void*) m_Doc->DocPages.at(OwnPage)); + break; + case NSRframe: + qDebug() << "Frame range is prohibited for end-notes"; + Q_ASSERT(false); + break; + } + } + else + //create new footnotes frame for that text frame + nF = m_Doc->createNoteFrame(this, note->notesStyle(), m_Doc->DocItems.indexOf(lastItem)); + //insert in map noteframe with empty list of notes + m_notesFramesMap.insert(nF, QList<TextNote*>()); + m_Doc->setNotesChanged(true); + } + else if (NS->isEndNotes()) + {//check endnotes frame proper page + const ScPage* scP = m_Doc->page4EndNotes(NS, this); + if (scP->pageNr() != nF->OwnPage) + { + double x,y; + x = scP->Margins.Left + m_Doc->rulerXoffset + scP->xOffset(); + y = scP->Margins.Top + m_Doc->rulerYoffset + scP->yOffset(); + if ((scP->pageNr() != nF->OwnPage) || (nF->xPos() > (x + scP->width())) || nF->yPos() > (y + scP->height())) + { + undoManager->setUndoEnabled(false); + nF->setXYPos(x,y); + undoManager->setUndoEnabled(true); + } + } + } + QList<TextNote*> nList;//list of notes in current noteFrame + nList = notesMap.value(nF); + if (!nList.contains(note)) + { + nList.append(note); + notesMap.insert(nF, nList); + } + if (!nF->isEndNotesFrame()) + lastItem = nF; + } + else + break; + ++it; + } + return notesMap; +} + +void PageItem_TextFrame::updateNotesMarks(NotesInFrameMap notesMap) +{ + bool docWasChanged = false; + +// QList<PageItem_NoteFrame*> curr_footNotesList; +// QList<PageItem_NoteFrame*> old_footNotesList; +// QList<PageItem_NoteFrame*> curr_endNotesList; +// QList<PageItem_NoteFrame*> old_endNotesList; + + +// foreach(PageItem_NoteFrame* nF, notesMap.keys()) +// { +// if (nF->isEndNotesFrame()) +// curr_endNotesList.append(nF); +// else if (!notesMap.value(nF).isEmpty()) +// curr_footNotesList.append(nF); +// } +// foreach(PageItem_NoteFrame* nF, m_notesFramesMap.keys()) +// { +// if (nF->isEndNotesFrame()) +// old_endNotesList.append(nF); +// else +// old_footNotesList.append(nF); +// } +// //check for endnotes marks change in current frame +// foreach (PageItem_NoteFrame* nF, old_endNotesList) +// { +// if (nF->deleteIt) +// { +// m_Doc->delNoteFrame(nF,true); +// docWasChanged = true; +// } +// else if (!notesMap.contains(nF) || (m_notesFramesMap.value(nF) != notesMap.value(nF))) +// { +// m_Doc->endNoteFrameChanged(nF); +// docWasChanged = true; +// } +// } + //check if some notes frames are not used anymore + foreach (PageItem_NoteFrame* nF, m_notesFramesMap.keys()) + { + if (nF->deleteIt || (nF->isAutoNoteFrame() && !notesMap.keys().contains(nF))) + { + m_Doc->delNoteFrame(nF,true); + docWasChanged = true; + } + else + { + QList<TextNote*> nList = notesMap.value(nF); + if (nList != nF->notesList() || m_Doc->notesChanged()) + { + nF->updateNotes(nList, (!nF->isEndNotesFrame() && !nF->notesList().isEmpty())); + docWasChanged = true; + } + } + } + if (m_notesFramesMap != notesMap) + { + docWasChanged = true; + foreach (PageItem_NoteFrame* nF, m_notesFramesMap.keys()) + { + if (notesMap.contains(nF)) + { + m_notesFramesMap.insert(nF, notesMap.value(nF)); + notesMap.remove(nF); + } + else if (nF->isAutoNoteFrame() || nF->isEndNotesFrame()) + m_notesFramesMap.remove(nF); + } + m_notesFramesMap.unite(notesMap); + } + if (docWasChanged) + { + m_Doc->flag_restartMarksRenumbering = true; + m_Doc->setNotesChanged(true); + } +} + +void PageItem_TextFrame::notesFramesLayout() +{ + foreach (PageItem_NoteFrame* nF, m_notesFramesMap.keys()) + { + if (nF == NULL) + continue; + if (nF->deleteIt) + continue; + if (nF->isEndNotesFrame() && m_Doc->flag_updateEndNotes) + m_Doc->updateEndNotesFrameContent(nF); + nF->invalid = true; + nF->layout(); + } +} + +int PageItem_TextFrame::removeMarksFromText(bool doUndo) +{ + int num = 0; + if (!isNoteFrame()) + { + TextNote* note = selectedNoteMark(true); + while (note != NULL) + { + if (doUndo && UndoManager::undoEnabled()) + m_Doc->setUndoDelNote(note); + if (note->isEndNote()) + m_Doc->flag_updateEndNotes = true; + m_Doc->deleteNote(note); + note = selectedNoteMark(true); + ++num; + } + } + + Mark* mrk = selectedMark(true); + while (mrk != NULL) + { + Q_ASSERT(!mrk->isNoteType()); + if (doUndo) + m_Doc->setUndoDelMark(mrk); + m_Doc->eraseMark(mrk, true, this); + mrk = selectedMark(true); + ++num; + } + return num; +} + +PageItem_NoteFrame *PageItem_TextFrame::itemNoteFrame(NotesStyle *nStyle) +{ + foreach (PageItem_NoteFrame* nF, m_notesFramesMap.keys()) + if (nF->notesStyle() == nStyle) + return nF; + return NULL; +} + +void PageItem_TextFrame::setNoteFrame(PageItem_NoteFrame *nF) { - invalidateLayout(); + m_notesFramesMap.insert(nF, nF->notesList()); } void PageItem_TextFrame::setMaxY(double y) diff --git Scribus/scribus/pageitem_textframe.h Scribus/scribus/pageitem_textframe.h index 50bd63d..31e0c0f 100644 --- Scribus/scribus/pageitem_textframe.h +++ Scribus/scribus/pageitem_textframe.h @@ -29,10 +29,15 @@ for which a new license (GPL+exception) is in place. #include "scribusapi.h" #include "pageitem.h" +#include "marks.h" +#include "notesstyles.h" +class PageItem_NoteFrame; class ScPainter; class ScribusDoc; +typedef QMap<PageItem_NoteFrame*, QList<TextNote *> > NotesInFrameMap; + #include "text/nlsconfig.h" #ifdef NLS_PROTO @@ -43,6 +48,9 @@ class ScText; class ScStyleRun; #endif +//cezaryece: I remove static statement and made it public as this function is used also by PageItem_NoteFrame +double calculateLineSpacing (const ParagraphStyle &style, PageItem *item); + class SCRIBUS_API PageItem_TextFrame : public PageItem { Q_OBJECT @@ -68,15 +76,24 @@ public: void ExpandSel(int dir, int oldPos); void deselectAll(); - virtual void invalidateLayout(); + //for speed up updates when changed was only one frame from chain + virtual void invalidateLayout(bool wholeChain = false); virtual void layout(); + //return true if all previouse frames from chain are valid (including that one) + bool isValidChainFromBegin(); + //simplify conditions checking if frame is in chain + //FIX: use it in other places + bool isInChain() { return ((prevInChain() != NULL) || (nextInChain() != NULL)); } double columnWidth(); #ifdef NLS_PROTO int firstTextItem() const { return itemText.firstFrameItem; } int lastTextItem() const { return itemText.lastFrameItem; } #endif + //enable/disable marks inserting actions depending on editMode + void togleEditModeActions(); QRegion availableRegion() { return m_availableRegion; } + protected: QRegion calcAvailableRegion(); QRegion m_availableRegion; @@ -116,15 +133,44 @@ private: QMap<QString,StoryText> shadows; bool checkKeyIsShortcut(QKeyEvent *k); +private slots: + void slotInvalidateLayout(); + +public: + //for footnotes/endnotes + bool hasMark(NotesStyle* NS = NULL); + bool hasNoteFrame(NotesStyle* NS, bool inChain = false); + //bool hasNoteFrame(PageItem_NoteFrame* nF) { return m_notesFramesMap.contains(nF); } + void delAllNoteFrames(bool doUpdate = false); + void removeNoteFrame(PageItem_NoteFrame* nF) { m_notesFramesMap.remove(nF); } + //layout notes frames /updates endnotes frames content if m_Doc->flag_updateEndNotes is set/ + void notesFramesLayout(); + //removing all marsk from text, returns number of removed marks + int removeMarksFromText(bool doUndo); + //return note frame for given notes style if current text frame has notes marks with this style + PageItem_NoteFrame* itemNoteFrame(NotesStyle* nStyle); + //list all notes frames for current text frame /with endnotes frames if endnotes marks are in that frame/ + QList<PageItem_NoteFrame*> notesFramesList() { return m_notesFramesMap.keys(); } + //list of notes inserted by current text frame into given noteframe + QList<TextNote*> notesList(PageItem_NoteFrame* nF) { return m_notesFramesMap.value(nF); } + //insert note frame to list with empty notes list + void setNoteFrame(PageItem_NoteFrame* nF); + void invalidateNotesFrames(); + +private: + NotesInFrameMap m_notesFramesMap; + NotesInFrameMap updateNotesFrames(QMap<int, Mark*> noteMarksPosMap); //update notes frames content + void updateNotesMarks(NotesInFrameMap notesMap); + Mark* selectedMark(bool onlySelection = true); + TextNote* selectedNoteMark(ScText* &hl, bool onlySelection = true); + TextNote* selectedNoteMark(bool onlySelection = true); +protected: // set text frame height to last line of text double maxY; void setMaxY(double y); public: void setTextFrameHeight(); - -private slots: - void slotInvalidateLayout(); }; #endif diff --git Scribus/scribus/pagestructs.h Scribus/scribus/pagestructs.h index 5f66292..74571ed 100644 --- Scribus/scribus/pagestructs.h +++ Scribus/scribus/pagestructs.h @@ -48,9 +48,12 @@ typedef enum Type_I_II_III, Type_a_b_c, Type_A_B_C, + Type_asterix, Type_None=99 } DocumentSectionType; +typedef DocumentSectionType NumerationType; + struct DocumentSection { uint number; //Just an index in the section list diff --git Scribus/scribus/plugins/fileloader/scribus150format/scribus150format.cpp Scribus/scribus/plugins/fileloader/scribus150format/scribus150format.cpp index caea86d..63f41d2 100644 --- Scribus/scribus/plugins/fileloader/scribus150format/scribus150format.cpp +++ Scribus/scribus/plugins/fileloader/scribus150format/scribus150format.cpp @@ -11,7 +11,9 @@ for which a new license (GPL+exception) is in place. #include "commonstrings.h" #include "ui/missing.h" #include "hyphenator.h" +#include "notesstyles.h" #include "pageitem_latexframe.h" +#include "pageitem_noteframe.h" #include "prefsmanager.h" #include "scclocale.h" #include "scconfig.h" @@ -27,6 +29,7 @@ for which a new license (GPL+exception) is in place. #include "util.h" #include "util_math.h" #include "util_color.h" +#include "util_text.h" #include "scgzfile.h" #ifdef HAVE_OSG #include "pageitem_osgframe.h" @@ -35,6 +38,7 @@ for which a new license (GPL+exception) is in place. #include "pageitem_regularpolygon.h" #include "pageitem_arc.h" #include "pageitem_spiral.h" +#include "pagestructs.h" #include <QCursor> // #include <QDebug> #include <QFileInfo> @@ -380,6 +384,26 @@ bool Scribus150Format::loadElements(const QString & data, QString fileDir, int t success = readPattern(m_Doc, reader, fileDir); if (!success) break; } + if (tagName == "NotesStyles") + { + success = readNotesStyles(m_Doc, reader); + if (!success) break; + } + if (tagName == "NotesFrames") + { + success = readNotesFrames(reader); + if (!success) break; + } + if (tagName == "Notes") + { + success = readNotes(m_Doc, reader); + if (!success) break; + } + if (tagName == "Marks") + { + success = readMarks(m_Doc, reader); + if (!success) break; + } } if (reader.hasError()) { @@ -858,6 +882,26 @@ bool Scribus150Format::loadPalette(const QString & fileName) success = readPattern(m_Doc, reader, fileDir); if (!success) break; } + if (tagName == "NotesStyles") + { + success = readNotesStyles(m_Doc, reader); + if (!success) break; + } + if (tagName == "NotesFrames") + { + success = readNotesFrames(reader); + if (!success) break; + } + if (tagName == "Notes") + { + success = readNotes(m_Doc, reader); + if (!success) break; + } + if (tagName == "Marks") + { + success = readMarks(m_Doc, reader); + if (!success) break; + } } if (reader.hasError()) @@ -1181,6 +1225,13 @@ bool Scribus150Format::loadFile(const QString & fileName, const FileFormat & /* QStack< QList<PageItem*> > groupStackP; QStack<int> groupStack2; + markeredItemsMap.clear(); + markeredMarksMap.clear(); + nsetRangeItemNamesMap.clear(); + notesFramesData.clear(); + notesMasterMarks.clear(); + notesNSets.clear(); + QString f(readSLA(fileName)); if (f.isEmpty()) { @@ -1493,6 +1544,26 @@ bool Scribus150Format::loadFile(const QString & fileName, const FileFormat & /* if (!success) break; } + if (tagName == "NotesStyles") + { + success = readNotesStyles(m_Doc, reader); + if (!success) break; + } + if (tagName == "NotesFrames") + { + success = readNotesFrames(reader); + if (!success) break; + } + if (tagName == "Notes") + { + success = readNotes(m_Doc, reader); + if (!success) break; + } + if (tagName == "Marks") + { + success = readMarks(m_Doc, reader); + if (!success) break; + } } if (reader.hasError()) @@ -1804,6 +1875,8 @@ bool Scribus150Format::loadFile(const QString & fileName, const FileFormat & /* gItem->groupItemList = gpL; } } + //update names to pointers + updateNames2Ptr(); // reestablish first/lastAuto m_Doc->FirstAuto = m_Doc->LastAuto; @@ -2367,7 +2440,6 @@ void Scribus150Format::readCharacterStyleAttrs(ScribusDoc *doc, ScXmlStreamAttri if (attrs.hasAttribute(LANGUAGE)) newStyle.setLanguage(attrs.valueAsString(LANGUAGE)); - static const QString SHORTCUT("SHORTCUT"); if (attrs.hasAttribute(SHORTCUT)) newStyle.setShortcut(attrs.valueAsString(SHORTCUT)); @@ -3074,6 +3146,167 @@ bool Scribus150Format::readTableOfContents(ScribusDoc* doc, ScXmlStreamReader& r return !reader.hasError(); } +bool Scribus150Format::readNotesStyles(ScribusDoc* doc, ScXmlStreamReader& reader) +{ + QStringRef tagName = reader.name(); + while(!reader.atEnd() && !reader.hasError()) + { + reader.readNext(); + if (reader.isEndElement() && reader.name() == tagName) + break; + //read notes styles + if (reader.isStartElement() && reader.name() == "notesStyle") + { + ScXmlStreamAttributes attrs = reader.scAttributes(); + NotesStyle NS; + NS.setName(attrs.valueAsString("Name")); + NS.setStart(attrs.valueAsInt("Start")); + NS.setEndNotes(attrs.valueAsBool("Endnotes")); + QString type = attrs.valueAsString("Type"); + if (type == "Type_1_2_3") + NS.setType(Type_1_2_3); + else if (type == "Type_i_ii_iii") + NS.setType(Type_i_ii_iii); + else if (type == "Type_I_II_III") + NS.setType(Type_I_II_III); + else if (type == "Type_a_b_c") + NS.setType(Type_a_b_c); + else if (type == "Type_A_B_C") + NS.setType(Type_A_B_C); + else if (type == "Type_asterix") + NS.setType(Type_asterix); + else //if (type == "Type_None") + NS.setType(Type_None); + NS.setRange((NumerationRange) attrs.valueAsInt("Range")); + NS.setPrefix(attrs.valueAsString("Prefix")); + NS.setSuffix(attrs.valueAsString("Suffix")); + NS.setAutoNotesHeight(attrs.valueAsBool("AutoHeight")); + NS.setAutoNotesWidth(attrs.valueAsBool("AutoWidth")); + NS.setAutoRemoveEmptyNotesFrames(attrs.valueAsBool("AutoRemove")); + NS.setAutoWeldNotesFrames(attrs.valueAsBool("AutoWeld")); + NS.setSuperscriptInNote(attrs.valueAsBool("SuperNote")); + NS.setSuperscriptInMaster(attrs.valueAsBool("SuperMaster")); + NS.setMarksCharStyle(""); + NS.setNotesParStyle(""); + QString name; + name = attrs.valueAsString("MarksStyle"); + if (!name.isEmpty()) + NS.setMarksCharStyle(name); + name = attrs.valueAsString("NotesStyle"); + if (!name.isEmpty()) + NS.setNotesParStyle(name); + + m_Doc->newNotesStyle(NS); + } + } + return !reader.hasError(); +} + +bool Scribus150Format::readNotesFrames(ScXmlStreamReader& reader) +{ + notesFramesData.clear(); + QStringRef tagName = reader.name(); + while(!reader.atEnd() && !reader.hasError()) + { + reader.readNext(); + if (reader.isEndElement() && reader.name() == tagName) + break; + if (reader.isStartElement()) + { + ScXmlStreamAttributes attrs = reader.scAttributes(); + NoteFrameData eF; + eF.NSname = attrs.valueAsString("NSname"); + eF.myID = attrs.valueAsInt("myID"); + if (reader.name() == "ENDNOTEFRAME") + { + eF.index = attrs.valueAsInt("index"); + eF.NSrange = (NumerationRange) attrs.valueAsInt("range"); + eF.itemID = attrs.valueAsInt("ItemID"); + } + if (reader.name() == "FOOTNOTEFRAME") + eF.itemID = attrs.valueAsInt("MasterID"); + notesFramesData.append(eF); + } + } + return !reader.hasError(); +} + +bool Scribus150Format::readNotes(ScribusDoc* doc, ScXmlStreamReader& reader) +{ + //read notes + QStringRef tagName = reader.name(); + while(!reader.atEnd() && !reader.hasError()) + { + reader.readNext(); + if (reader.isEndElement() && reader.name() == tagName) + break; + if (reader.isStartElement() && reader.name() == "Note") + { + ScXmlStreamAttributes attrs = reader.scAttributes(); + TextNote* note = m_Doc->newNote(NULL); + note->setSaxedText(attrs.valueAsString("Text")); + //temporaly insert names of master mark and notes style into maps with note pointer + //will be resolved to pointers by updateNames2Ptr() after all will read + notesMasterMarks.insert(attrs.valueAsString("Master"), note); + notesNSets.insert(note, attrs.valueAsString("NStyle")); + } + } + return !reader.hasError(); +} + +bool Scribus150Format::readMarks(ScribusDoc* doc, ScXmlStreamReader& reader) +{ + QStringRef tagName = reader.name(); + while(!reader.atEnd() && !reader.hasError()) + { + reader.readNext(); + if (reader.isEndElement() && reader.name() == tagName) + break; + if(reader.isStartElement() && reader.name() == "Mark") + { + ScXmlStreamAttributes attrs = reader.scAttributes(); + + QString label = ""; + if (attrs.hasAttribute("label")) + label = attrs.valueAsString("label"); + + MarkType type = MARKNoType; + if (attrs.hasAttribute("type")) + type = (MarkType) attrs.valueAsInt("type"); + + if (label != "" && type != MARKNoType) + { + Mark* mark = doc->newMark(); + mark->label=attrs.valueAsString("label"); + mark->setType(type); + + if (type == MARKVariableTextType && attrs.hasAttribute("str")) + mark->setString(attrs.valueAsString("str")); + if (type == MARK2ItemType && attrs.hasAttribute("ItemID")) + { + //QString itemName = attrs.valueAsString("itemName"); + markeredItemsMap.insert(mark, attrs.valueAsInt("ItemID")); + } + if (type == MARK2MarkType && attrs.hasAttribute("MARKlabel")) + { + QString mark2Label = attrs.valueAsString("MARKlabel"); + MarkType mark2Type = (MarkType) attrs.valueAsInt("MARKtype"); + Mark* mark2 = doc->getMarkDefinied(mark2Label, mark2Type); + if (mark2 != NULL) //mark is not defined yet, insert into temp list for update to pointers later + mark->setMark(mark2); + else + { + QMap<QString, MarkType> mark2map; + mark2map.insert(mark2Label, mark2Type); + markeredMarksMap.insert(mark, mark2map); + } + } + } + } + } + return !reader.hasError(); +} + bool Scribus150Format::readSections(ScribusDoc* doc, ScXmlStreamReader& reader) { QStringRef tagName = reader.name(); @@ -3534,6 +3767,60 @@ bool Scribus150Format::readObject(ScribusDoc* doc, ScXmlStreamReader& reader, It doc->Items = DItems; } } + if (tName == "MARK") + { + if (newItem->asTextFrame()) + { + QString l = tAtt.valueAsString("label"); + MarkType t = (MarkType) tAtt.valueAsInt("type"); + Mark* mark = NULL; + if (m_Doc->isLoading()) + { + mark = m_Doc->getMarkDefinied(l, t); + } + else + { //doc is not loading so it is copy/paste task + if (t == MARKVariableTextType) + mark = m_Doc->getMarkDefinied(l, t); + else + { + //create copy of mark + Mark* oldMark = m_Doc->getMarkDefinied(l, t); + if (oldMark == NULL) + { + qWarning() << "wrong copy of oldMark"; + mark = m_Doc->newMark(); + mark->setType(t); + } + else + { + mark = m_Doc->newMark(oldMark); + getUniqueName(l,doc->marksLabelsList(t), "_"); + } + mark->label = l; + if (t == MARKNoteMasterType) + { //create copy of note + TextNote* old = mark->getNotePtr(); + TextNote* note = m_Doc->newNote(old->notesStyle()); + mark->setNotePtr(note); + note->setMasterMark(mark); + note->setSaxedText(old->saxedText()); + m_Doc->setNotesChanged(true); + } + } + } + if (mark == NULL) + qDebug() << "Undefinied mark label ["<< l << "] type " << t; + else + { + //set pointer to item holds mark in his text + if (t == MARKAnchorType) + mark->setItemPtr(newItem); + mark->OwnPage = newItem->OwnPage; + newItem->itemText.insertMark(mark, newItem->itemText.length()); + } + } + } if (tName == "WeldEntry") { PageItem::weldingInfo wInf; @@ -4008,6 +4295,7 @@ PageItem* Scribus150Format::pasteItem(ScribusDoc *doc, ScXmlStreamAttributes& at bool isGroupFlag = attrs.valueAsBool("isGroupControl", 0); if (isGroupFlag) pt = PageItem::Group; + bool isNoteFrameFlag = attrs.valueAsBool("isNoteFrame", 0); double xf, yf; double x = attrs.valueAsDouble("XPOS"); double y = attrs.valueAsDouble("YPOS"); @@ -4130,7 +4418,7 @@ PageItem* Scribus150Format::pasteItem(ScribusDoc *doc, ScXmlStreamAttributes& at currItem->OwnPage = pagenr; break; case PageItem::TextFrame: - z = doc->itemAdd(PageItem::TextFrame, PageItem::Unspecified, x, y, w, h, pw, CommonStrings::None, Pcolor, true); + z = doc->itemAdd(PageItem::TextFrame, PageItem::Unspecified, x, y, w, h, pw, CommonStrings::None, Pcolor, true, isNoteFrameFlag); currItem = doc->Items->at(z); if (pagenr > -2) currItem->OwnPage = pagenr; @@ -4310,10 +4598,10 @@ PageItem* Scribus150Format::pasteItem(ScribusDoc *doc, ScXmlStreamAttributes& at } } currItem->setRotation( attrs.valueAsDouble("ROT", 0.0) ); - currItem->setTextToFrameDist(attrs.valueAsDouble("EXTRA", 1.0), - attrs.valueAsDouble("REXTRA", 1.0), - attrs.valueAsDouble("TEXTRA", 1.0), - attrs.valueAsDouble("BEXTRA", 1.0)); + currItem->setTextToFrameDist(attrs.valueAsDouble("EXTRA", 0.0), + attrs.valueAsDouble("REXTRA", 0.0), + attrs.valueAsDouble("TEXTRA", 0.0), + attrs.valueAsDouble("BEXTRA", 0.0)); currItem->setFirstLineOffset(static_cast<FirstLineOffsetPolicy>(attrs.valueAsInt("FLOP"))); currItem->PLineArt = Qt::PenStyle(attrs.valueAsInt("PLINEART", 0)); @@ -5175,6 +5463,13 @@ bool Scribus150Format::loadPage(const QString & fileName, int pageNumber, bool M WeldItems.clear(); WeldID.clear(); + markeredItemsMap.clear(); + markeredMarksMap.clear(); + nsetRangeItemNamesMap.clear(); + notesFramesData.clear(); + notesMasterMarks.clear(); + notesNSets.clear(); + QString f(readSLA(fileName)); if (f.isEmpty()) { @@ -5931,6 +6226,14 @@ bool Scribus150Format::readPageCount(const QString& fileName, int *num1, int *nu QString pageName; int counter = 0; int counter2 = 0; + + markeredItemsMap.clear(); + markeredMarksMap.clear(); + nsetRangeItemNamesMap.clear(); + notesFramesData.clear(); + notesMasterMarks.clear(); + notesNSets.clear(); + QString f(readSLA(fileName)); if (f.isEmpty()) return false; @@ -5971,3 +6274,147 @@ bool Scribus150Format::readPageCount(const QString& fileName, int *num1, int *nu *num2 = counter2; return success; } + +void Scribus150Format::updateNames2Ptr() //after document load - items pointers should be updated +{ + if (!markeredItemsMap.isEmpty()) + { + QMap<Mark*, int>::Iterator markIt; + QMap<Mark*, int>::Iterator end = markeredItemsMap.end(); + for (markIt = markeredItemsMap.begin(); markIt != end; ++markIt) + { + Mark* mrk = markIt.key(); + int ItemID = markIt.value(); + if (LinkID.contains(ItemID)) + { + mrk->setItemPtr(LinkID[ItemID]); + mrk->setString(QString("%1").arg(mrk->getItemPtr()->OwnPage +1)); + } + else + { + qWarning() << "Scribus150Format::updateNames2Ptr() : wrong mark [" << mrk->label << "] data - item [" << ItemID << "] not exists - DELETING MARK"; + if (!m_Doc->eraseMark(mrk, true)) + qWarning() << "Erase mark [" << mrk->label << "] failed - was it definied?"; + } + } + markeredItemsMap.clear(); + } + if (!markeredMarksMap.isEmpty()) + { + QMap<Mark*,QMap<QString, MarkType> >::iterator markIt; + QMap<Mark*,QMap<QString, MarkType> >::iterator end = markeredMarksMap.end(); + for (markIt = markeredMarksMap.begin(); markIt != end; ++markIt) + { + Mark* mark = markIt.key(); + QMap<QString, MarkType> mark2map = markIt.value(); + QString label2 = mark2map.begin().key(); + MarkType type2 = mark2map.begin().value(); + Mark* mark2 = m_Doc->getMarkDefinied(label2, type2); + if (mark2 != NULL) + { + mark->setMark(mark2); + } + else + { + qWarning() << "Scribus150Format::updateNames2Ptr() : wrong mark [" << mark->label << "] data - pointed mark name [" << label2 << "] not exists - DELETING MARK"; + if (!m_Doc->eraseMark(mark, true)) + qWarning() << "Erase mark [" << mark->label << "] failed - was it definied?"; + + } + } + markeredMarksMap.clear(); + } + + //update endnotes frames pointers + if (!notesFramesData.isEmpty()) + { + for (int i = 0; i < notesFramesData.count(); ++i) + { + NoteFrameData eF = notesFramesData.at(i); + NotesStyle* NS = m_Doc->getNotesStyle(eF.NSname); + if (NS != NULL) + { + PageItem* item = LinkID.value(eF.myID); + if ((item != NULL) && item->isNoteFrame()) + { + item->asNoteFrame()->setNS(NS); + if (NS->isEndNotes()) + { + if (eF.NSrange == NSRdocument) + m_Doc->setEndNoteFrame(item->asNoteFrame(), (void*) NULL); + else if (eF.NSrange == NSRpage) + m_Doc->setEndNoteFrame(item->asNoteFrame(), (void*) m_Doc->DocPages.at(eF.index)); + else if (eF.NSrange == NSRsection) + m_Doc->setEndNoteFrame(item->asNoteFrame(), m_Doc->getSectionKeyForPageIndex(eF.index)); + else if (eF.NSrange == NSRstory) + m_Doc->setEndNoteFrame(item->asNoteFrame(), (void*) LinkID.value(eF.itemID)); + } + else + { + PageItem* master = LinkID.value(eF.itemID); + item->asNoteFrame()->setMaster(master); + master->asTextFrame()->setNoteFrame(item->asNoteFrame()); + //FIX welding with note frame + PageItem::weldingInfo wInf; + for (int i = 0 ; i < master->weldList.count(); i++) + { + wInf = master->weldList.at(i); + if (wInf.weldID == eF.myID) + { + master->weldList[i].weldItem = item; + break; + } + } + } + } + else + qDebug() << "Scribus150Format::updateNames2Ptr() : update end frames pointers - item is not note frame or name is wrong"; + } + } + } + //update pointers to notes in master notes marks + if (!notesMasterMarks.isEmpty()) + { + assert(!m_Doc->marksList().isEmpty() && !m_Doc->notesList().isEmpty()); + QMap<QString, TextNote*>::Iterator it; + QMap<QString, TextNote*>::Iterator end = notesMasterMarks.end(); + for (it = notesMasterMarks.begin(); it != end; ++it) + { + TextNote* note = it.value(); + assert(note != NULL); + QString mrkLabel = it.key(); + Mark* mrk = m_Doc->getMarkDefinied(mrkLabel, MARKNoteMasterType); + if (mrk == NULL) + { + qWarning() << "Scribus150Format::updateNames2Ptr() : cannot find master mark ("<<mrkLabel <<") for note - note will be deleted"; + m_Doc->deleteNote(note); + continue; + } + note->setMasterMark(mrk); + mrk->setNotePtr(note); + } + notesMasterMarks.clear(); + } + if (!notesNSets.isEmpty()) + { + assert(!m_Doc->notesList().isEmpty()); + QMap<TextNote*, QString>::iterator it; + QMap<TextNote*, QString>::iterator end = notesNSets.end(); + for (it = notesNSets.begin(); it != end; ++it) + { + TextNote* note = it.key(); + assert(note != NULL); + QString nsLabel = it.value(); + NotesStyle* ns = m_Doc->getNotesStyle(nsLabel); + if (ns != NULL) + note->setNotesStyle(ns); + if (note->notesStyle() == NULL) + { + qWarning() << "Scribus150Format::updateNames2Ptr() : cannot find notes style ("<<nsLabel <<") for note - note will be deleted"; + m_Doc->deleteNote(note); + continue; + } + } + notesNSets.clear(); + } +} diff --git Scribus/scribus/plugins/fileloader/scribus150format/scribus150format.h Scribus/scribus/plugins/fileloader/scribus150format/scribus150format.h index a77fc8f..85bcfb5 100644 --- Scribus/scribus/plugins/fileloader/scribus150format/scribus150format.h +++ Scribus/scribus/plugins/fileloader/scribus150format/scribus150format.h @@ -9,6 +9,7 @@ for which a new license (GPL+exception) is in place. #include "pluginapi.h" #include "loadsaveplugin.h" +#include "notesstyles.h" #include "scfonts.h" #include "scribusstructs.h" #include "styles/styleset.h" @@ -125,6 +126,27 @@ class PLUGIN_API Scribus150Format : public LoadSavePlugin bool readPrinterOptions(ScribusDoc* doc, ScXmlStreamReader& reader); bool readSections(ScribusDoc* doc, ScXmlStreamReader& reader); bool readTableOfContents(ScribusDoc* doc, ScXmlStreamReader& reader); + bool readNotes(ScribusDoc* doc, ScXmlStreamReader& reader); + bool readNotesStyles(ScribusDoc* doc, ScXmlStreamReader& reader); + bool readNotesFrames(ScXmlStreamReader &reader); + bool readMarks(ScribusDoc* doc, ScXmlStreamReader& reader); + + //lists of items and marks with names only, which need update to pointers + QMap<Mark*, int> markeredItemsMap; + QMap<Mark*, QMap<QString, MarkType> > markeredMarksMap; + QMap<QString, int> nsetRangeItemNamesMap; + QMap<QString, TextNote*> notesMasterMarks; + QMap<TextNote*, QString> notesNSets; + struct NoteFrameData { + QString NSname; + int myID; + int itemID; + int index; + NumerationRange NSrange; + }; + QList<NoteFrameData> notesFramesData; + + void updateNames2Ptr(); //after document load items pointers should be updated in markeredItemList PageItem* pasteItem(ScribusDoc *doc, ScXmlStreamAttributes& attrs, const QString& baseDir, int pagenr = -2 /* currentPage*/); @@ -151,6 +173,10 @@ class PLUGIN_API Scribus150Format : public LoadSavePlugin void writePdfOptions(ScXmlStreamWriter& docu); void writeDocItemAttributes(ScXmlStreamWriter& docu); void writeTOC(ScXmlStreamWriter& docu); + void writeMarks(ScXmlStreamWriter & docu); + void writeNotesStyles(ScXmlStreamWriter & docu); + void writeNotesFrames(ScXmlStreamWriter & docu); + void writeNotes(ScXmlStreamWriter & docu); void writePageSets(ScXmlStreamWriter& docu); void writeSections(ScXmlStreamWriter& docu); void writePatterns(ScXmlStreamWriter& docu, const QString& baseDir, bool part = false, Selection* selection = 0); diff --git Scribus/scribus/plugins/fileloader/scribus150format/scribus150format_save.cpp Scribus/scribus/plugins/fileloader/scribus150format/scribus150format_save.cpp index 8fe3f7f..976b314 100644 --- Scribus/scribus/plugins/fileloader/scribus150format/scribus150format_save.cpp +++ Scribus/scribus/plugins/fileloader/scribus150format/scribus150format_save.cpp @@ -20,6 +20,7 @@ for which a new license (GPL+exception) is in place. #include "scribusdoc.h" #include "scribusview.h" #include "hyphenator.h" +#include "notesstyles.h" #include "pageitem_latexframe.h" #ifdef HAVE_OSG #include "pageitem_osgframe.h" @@ -28,6 +29,7 @@ for which a new license (GPL+exception) is in place. #include "pageitem_arc.h" #include "pageitem_spiral.h" #include "pageitem_table.h" +#include "pageitem_noteframe.h" #include "units.h" #include "util.h" @@ -71,6 +73,9 @@ QString Scribus150Format::saveElements(double xp, double yp, double wp, double h emG.append(currItem); if ((currItem->asTextFrame()) || (currItem->asPathText())) { + //for notes frames text should not be saved + if (currItem->isNoteFrame()) + continue; for (int e = currItem->firstInFrame(); e <= currItem->lastInFrame(); ++e) { uint chr = currItem->itemText.text(e).unicode(); @@ -386,6 +391,10 @@ bool Scribus150Format::saveFile(const QString & fileName, const FileFormat & /* writePdfOptions(docu); writeDocItemAttributes(docu); writeTOC(docu); + writeMarks(docu); + writeNotesStyles(docu); + writeNotesFrames(docu); + writeNotes(docu); writePageSets(docu); writeSections(docu); writePatterns(docu, fileDir); @@ -1188,6 +1197,9 @@ void Scribus150Format::writeSections(ScXmlStreamWriter & docu) case Type_A_B_C: docu.writeAttribute("Type", "Type_A_B_C"); break; + case Type_asterix: + docu.writeAttribute("Type", "Type_asterix"); + break; case Type_None: docu.writeAttribute("Type", "Type_None"); break; @@ -1201,6 +1213,154 @@ void Scribus150Format::writeSections(ScXmlStreamWriter & docu) docu.writeEndElement(); } +void Scribus150Format::writeMarks(ScXmlStreamWriter & docu) +{ + //write list of definied marks to SLA + if (m_Doc->marksList().isEmpty()) + return; + docu.writeStartElement("Marks"); + foreach(Mark* mrk, m_Doc->marksList()) + { + if (mrk->isType(MARKNoteFrameType)) + continue; + docu.writeEmptyElement("Mark"); + docu.writeAttribute("label", mrk->label); + docu.writeAttribute("type", mrk->getType()); + if (mrk->isType(MARK2ItemType) && mrk->hasItemPtr()) + { + const PageItem* item = mrk->getItemPtr(); + assert(item != NULL); + docu.writeAttribute("ItemID", qHash(item)); + //docu.writeAttribute("itemName", item->itemName()); + } + else if (mrk->isType(MARKVariableTextType) && mrk->hasString()) + docu.writeAttribute("str", mrk->getString()); + else if (mrk->isType(MARK2MarkType) && mrk->hasMark()) + { + QString label; + MarkType type; + mrk->getMark(label, type); + docu.writeAttribute("MARKlabel", label); + docu.writeAttribute("MARKtype", type); + } + } + docu.writeEndElement(); +} + +void Scribus150Format::writeNotesStyles(ScXmlStreamWriter & docu) +{ + //write notes styles + docu.writeStartElement("NotesStyles"); + QList<NotesStyle*>::Iterator itNS; + QList<NotesStyle*>::Iterator end = m_Doc->m_docNotesStylesList.end(); + for (itNS = m_Doc->m_docNotesStylesList.begin(); itNS != end; ++itNS) + { + NotesStyle* NS = (*itNS); + docu.writeEmptyElement("notesStyle"); + docu.writeAttribute("Name", NS->name()); + docu.writeAttribute("Start", NS->start()); + docu.writeAttribute("Endnotes", NS->isEndNotes()); + switch (NS->getType()) + { + case Type_1_2_3: + docu.writeAttribute("Type", "Type_1_2_3"); + break; + case Type_i_ii_iii: + docu.writeAttribute("Type", "Type_i_ii_iii"); + break; + case Type_I_II_III: + docu.writeAttribute("Type", "Type_I_II_III"); + break; + case Type_a_b_c: + docu.writeAttribute("Type", "Type_a_b_c"); + break; + case Type_A_B_C: + docu.writeAttribute("Type", "Type_A_B_C"); + break; + case Type_asterix: + docu.writeAttribute("Type", "Type_asterix"); + break; + case Type_None: + docu.writeAttribute("Type", "Type_None"); + break; + } + docu.writeAttribute("Range", (int) NS->range()); + docu.writeAttribute("Prefix", NS->prefix()); + docu.writeAttribute("Suffix", NS->suffix()); + docu.writeAttribute("AutoHeight", NS->isAutoNotesHeight()); + docu.writeAttribute("AutoWidth", NS->isAutoNotesWidth()); + docu.writeAttribute("AutoRemove", NS->isAutoRemoveEmptyNotesFrames()); + docu.writeAttribute("AutoWeld", NS->isAutoWeldNotesFrames()); + docu.writeAttribute("SuperNote", NS->isSuperscriptInNote()); + docu.writeAttribute("SuperMaster", NS->isSuperscriptInMaster()); + docu.writeAttribute("MarksStyle", NS->marksChStyle()); + docu.writeAttribute("NotesStyle", NS->notesParStyle()); + } + docu.writeEndElement(); +} + +void Scribus150Format::writeNotesFrames(ScXmlStreamWriter &docu) +{ + docu.writeStartElement("NotesFrames"); + + QList<PageItem_NoteFrame*> NFList; + foreach (NotesStyle* NS, m_Doc->m_docNotesStylesList) + NFList.append(m_Doc->listNotesFrames(NS)); + + for (int it = 0; it < NFList.count(); ++it) + { + PageItem_NoteFrame* nF = NFList.at(it); + NotesStyle* NS = nF->notesStyle(); + if (NS->isEndNotes()) + { + docu.writeEmptyElement("ENDNOTEFRAME"); + docu.writeAttribute("NSname", NS->name()); + docu.writeAttribute("range", (int) NS->range()); + docu.writeAttribute("myID", qHash(nF)); + //docu.writeAttribute("name", nF->itemName()); + + rangeItem rI = m_Doc->m_docEndNotesFramesMap.value(nF); + if (NS->range() == NSRsection) + docu.writeAttribute("index", rI.sectionIndex); + else if (NS->range() == NSRpage) + docu.writeAttribute("index", rI.page->pageNr()); + else if (NS->range() == NSRstory) + docu.writeAttribute("ItemID", qHash(rI.firstStoryFrame)); + //docu.writeAttribute("item", rI.firstStoryFrame->itemName()); + } + else //footnotes frame + { + docu.writeEmptyElement("FOOTNOTEFRAME"); + docu.writeAttribute("NSname", NS->name()); + docu.writeAttribute("myID", qHash(nF)); + //docu.writeAttribute("name", nF->itemName()); + docu.writeAttribute("MasterID", qHash(nF->masterFrame())); + //docu.writeAttribute("master",nF->masterFrame()->itemName()); + } + } + docu.writeEndElement(); +} + +void Scribus150Format::writeNotes(ScXmlStreamWriter & docu) +{ + //write notes + if (m_Doc->notesList().isEmpty()) + return; + docu.writeStartElement("Notes"); + QList<TextNote*>::const_iterator itTN; + QList<TextNote*>::const_iterator end = m_Doc->notesList().end(); + for (itTN = m_Doc->notesList().begin(); itTN != end; ++itTN) + { + TextNote* TN = (*itTN); + if (TN->masterMark() == NULL) + continue; + docu.writeEmptyElement("Note"); + docu.writeAttribute("Master", TN->masterMark()->label); + docu.writeAttribute("NStyle", TN->notesStyle()->name()); + docu.writeAttribute("Text", TN->saxedText()); + } + docu.writeEndElement(); +} void Scribus150Format::writePageSets(ScXmlStreamWriter & docu) { @@ -1350,7 +1510,10 @@ void Scribus150Format::writeITEXTs(ScribusDoc *doc, ScXmlStreamWriter &docu, Pag CharStyle lastStyle; int lastPos = 0; QString tmpnum; - for(int k = 0; k < item->itemText.length(); ++k) + int iTLen = item->itemText.length(); + if (item->isNoteFrame()) + iTLen = 0; //used for saving empty endnotes frames, as they will be filled automatically + for(int k = 0; k < iTLen; ++k) { const CharStyle& style1(item->itemText.charStyle(k)); const QChar ch = item->itemText.text(k); @@ -1398,6 +1561,13 @@ void Scribus150Format::writeITEXTs(ScribusDoc *doc, ScXmlStreamWriter &docu, Pag docu.writeAttribute("Unicode", tmpnum); docu.writeAttribute("COBJ", item->itemText.object(k)->inlineCharID); } + else if (ch == SpecialChars::OBJECT && item->itemText.item(k)->mark != NULL) + { + Mark* mark = item->itemText.item(k)->mark; + docu.writeEmptyElement("MARK"); + docu.writeAttribute("label", mark->label); + docu.writeAttribute("type", mark->getType()); + } else if (ch == SpecialChars::PARSEP) // stores also the paragraphstyle for preceding chars putPStyle(docu, item->itemText.paragraphStyle(k), "para"); else if (ch == SpecialChars::TAB) @@ -1711,6 +1881,9 @@ void Scribus150Format::WriteObjects(ScribusDoc *doc, ScXmlStreamWriter& docu, co else { docu.writeAttribute("BACKITEM", -1); + if (item->isNoteFrame()) + docu.writeAttribute("isNoteFrame", 1); + else writeITEXTs(doc, docu, item); } } @@ -2137,18 +2310,6 @@ void Scribus150Format::WriteObjects(ScribusDoc *doc, ScXmlStreamWriter& docu, co } docu.writeEndElement(); } - //write weld parameter - if (item->isWelded()) - { - for (int i = 0 ; i < item->weldList.count(); i++) - { - PageItem::weldingInfo wInf = item->weldList.at(i); - docu.writeEmptyElement("WeldEntry"); - docu.writeAttribute("Target", qHash(wInf.weldItem)); - docu.writeAttribute("WX", wInf.weldPoint.x()); - docu.writeAttribute("WY", wInf.weldPoint.y()); - } - } docu.writeEndElement(); } } @@ -2200,11 +2361,33 @@ void Scribus150Format::SetItemProps(ScXmlStreamWriter& docu, PageItem* item, con docu.writeAttribute("PLINEJOIN", item->PLineJoin); } //write weld parameter + //write weld parameter if (item->isWelded()) { + bool isWelded = false; + for (int i = 0 ; i < item->weldList.count(); i++) + { + PageItem::weldingInfo wInf = item->weldList.at(i); + PageItem *pIt = wInf.weldItem; + if (pIt == NULL) + { + qDebug() << "Saving welding info - empty pointer!!!"; + continue; + } + if (pIt->isAutoNoteFrame()) + continue; + isWelded = true; + docu.writeEmptyElement("WeldEntry"); + docu.writeAttribute("Target", qHash(wInf.weldItem)); + docu.writeAttribute("WX", wInf.weldPoint.x()); + docu.writeAttribute("WY", wInf.weldPoint.y()); + } + if (isWelded) + { docu.writeAttribute("isWeldItem", 1); docu.writeAttribute("WeldSource", qHash(item)); } + } if (item->asRegularPolygon()) { PageItem_RegularPolygon *regitem = item->asRegularPolygon(); diff --git Scribus/scribus/plugins/scriptplugin/scriptercore.cpp Scribus/scribus/plugins/scriptplugin/scriptercore.cpp index eed740f..a253226 100644 --- Scribus/scribus/plugins/scriptplugin/scriptercore.cpp +++ Scribus/scribus/plugins/scriptplugin/scriptercore.cpp @@ -18,6 +18,8 @@ for which a new license (GPL+exception) is in place. #include "runscriptdialog.h" #include "ui/helpbrowser.h" +#include "ui/marksmanager.h" +#include "ui/notesstyleseditor.h" #include "ui/propertiespalette.h" //TODO Move the calls to this to a signal #include "ui/pagepalette.h" //TODO Move the calls to this to a signal #include "ui/layers.h" //TODO Move the calls to this to a signal @@ -170,6 +172,8 @@ void ScripterCore::FinishScriptRun() if (ScMW->HaveDoc) { ScMW->propertiesPalette->setDoc(ScMW->doc); + ScMW->marksManager->setDoc(ScMW->doc); + ScMW->nsEditor->setDoc(ScMW->doc); ScMW->layerPalette->setDoc(ScMW->doc); ScMW->outlinePalette->setDoc(ScMW->doc); ScMW->outlinePalette->BuildTree(); diff --git Scribus/scribus/scribus.cpp Scribus/scribus/scribus.cpp index a0fc22f..915841c 100644 --- Scribus/scribus/scribus.cpp +++ Scribus/scribus/scribus.cpp @@ -100,11 +100,14 @@ for which a new license (GPL+exception) is in place. #include "gtgettext.h" #include "hyphenator.h" #include "langmgr.h" +#include "marks.h" +#include "notesstyles.h" #include "pageitem_group.h" #include "pageitem_imageframe.h" #include "pageitem_latexframe.h" #include "pageitem_table.h" #include "pageitem_textframe.h" +#include "pageitem_noteframe.h" #include "pagesize.h" #include "pdflib.h" #include "pdfoptions.h" @@ -164,6 +167,14 @@ for which a new license (GPL+exception) is in place. #include "ui/loremipsum.h" #include "ui/marginwidget.h" #include "ui/margindialog.h" +#include "ui/mark2item.h" +#include "ui/mark2mark.h" +#include "ui/markanchor.h" +#include "ui/marknote.h" +#include "ui/markvariabletext.h" +#include "ui/MarkInsertDlg.h" +#include "ui/marksmanager.h" +#include "ui/masterpagepalette.h" #include "ui/mergedoc.h" #include "ui/movepage.h" #include "ui/multipleduplicate.h" @@ -174,6 +185,7 @@ for which a new license (GPL+exception) is in place. #include "ui_nftdialog.h" #include "ui/nftwidget.h" #include "ui/nodeeditpalette.h" +#include "ui/notesstyleseditor.h" #ifdef HAVE_OSG #include "ui/osgeditor.h" #endif @@ -330,7 +342,7 @@ int ScribusMainWindow::initScMW(bool primaryMainWindow) PrefsContext *undoPrefs = prefsManager->prefsFile->getContext("undo"); undoManager->setUndoEnabled(undoPrefs->getBool("enabled", true)); tocGenerator = new TOCGenerator(); - + m_marksCount = 0; initDefaultValues(); @@ -379,6 +391,7 @@ int ScribusMainWindow::initScMW(bool primaryMainWindow) if (primaryMainWindow) ScCore->setSplashStatus( tr("Initializing Hyphenator") ); + QString preLang(prefsManager->appPrefs.hyphPrefs.Language); initHyphenator(); if (!LanguageManager::instance()->getHyphFilename( preLang, true ).isEmpty() ) @@ -591,6 +604,17 @@ void ScribusMainWindow::initPalettes() connect( styleManager, SIGNAL(paletteShown(bool)), scrActions["editStyles"], SLOT(setChecked(bool))); styleManager->installEventFilter(this); + // initializing mark`s manager + marksManager = new MarksManager(this, "marksManager"); + connect( scrActions["editMarks"], SIGNAL(toggled(bool)), marksManager, SLOT(setPaletteShown(bool)) ); + connect( marksManager, SIGNAL(paletteShown(bool)), scrActions["editMarks"], SLOT(setChecked(bool))); + marksManager->installEventFilter(this); + // initializing notes styles manager + nsEditor = new NotesStylesEditor(this, "notesStylesEditor"); + connect( scrActions["editNotesStyles"], SIGNAL(toggled(bool)), nsEditor, SLOT(setPaletteShown(bool)) ); + connect( nsEditor, SIGNAL(paletteShown(bool)), scrActions["editNotesStyles"], SLOT(setChecked(bool))); + nsEditor->installEventFilter(this); + // connect(docCheckerPalette, SIGNAL(selectElement(int, int)), this, SLOT(selectItemsFromOutlines(int, int))); connect(docCheckerPalette, SIGNAL(selectElementByItem(PageItem *, bool)), this, SLOT(selectItemsFromOutlines(PageItem *, bool))); connect(docCheckerPalette, SIGNAL(selectElement(PageItem *, bool, int)), this, SLOT(selectItemFromOutlines(PageItem *, bool, int))); @@ -728,6 +752,8 @@ void ScribusMainWindow::initMenuBar() // scrMenuMgr->addMenuItem(scrActions["editGradients"], "Edit", false); // scrMenuMgr->addMenuItem(scrActions["editPatterns"], "Edit", false); scrMenuMgr->addMenuItem(scrActions["editStyles"], "Edit", false); + scrMenuMgr->addMenuItem(scrActions["editMarks"], "Edit", false); + scrMenuMgr->addMenuItem(scrActions["editNotesStyles"], "Edit", false); scrMenuMgr->addMenuItem(scrActions["editMasterPages"], "Edit", false); scrMenuMgr->addMenuItem(scrActions["editJavascripts"], "Edit", false); scrMenuMgr->setMenuEnabled("EditPasteRecent", false); @@ -847,6 +873,9 @@ void ScribusMainWindow::initMenuBar() scrMenuMgr->addMenuItem(scrActions["itemWeld"], "Item", false); scrMenuMgr->addMenuItem(scrActions["itemEditWeld"], "Item", false); + scrMenuMgr->addMenuItem(scrActions["editMark"], "Item", false); + scrMenuMgr->addMenuItem(scrActions["itemUpdateMarks"], "Item", true); + //Insert menu scrMenuMgr->createMenu("Insert", ActionManager::defaultMenuNameEntryTranslated("Insert")); scrMenuMgr->addMenuItem(scrActions["insertFrame"], "Insert", false); @@ -936,6 +965,14 @@ void ScribusMainWindow::initMenuBar() scrMenuMgr->addMenuSeparator("Insert"); scrMenuMgr->addMenuItem(scrActions["insertSampleText"], "Insert", false); + scrMenuMgr->addMenuSeparator("Insert"); + scrMenuMgr->createMenu("InsertMark", tr("Marks"), "Insert"); + scrMenuMgr->addMenuItem(scrActions["insertMarkAnchor"], "InsertMark", false); + scrMenuMgr->addMenuItem(scrActions["insertMarkVariableText"], "InsertMark", false); + scrMenuMgr->addMenuItem(scrActions["insertMarkItem"], "InsertMark", false); + scrMenuMgr->addMenuItem(scrActions["insertMark2Mark"], "InsertMark", false); + scrMenuMgr->addMenuItem(scrActions["insertMarkNote"], "InsertMark", false); +// scrMenuMgr->addMenuItem(scrActions["insertMarkIndex"], "InsertMark", false); //Page menu scrMenuMgr->createMenu("Page", ActionManager::defaultMenuNameEntryTranslated("Page")); @@ -1140,6 +1177,7 @@ void ScribusMainWindow::setStatusBarInfoText(QString newText) //AV to be replaced with Selection::update and listener in PropertiesPalette void ScribusMainWindow::setTBvals(PageItem *currItem) { + scrActions["editMark"]->setEnabled(false); if (currItem->itemText.length() != 0) { // int ChPos = qMin(currItem->CPos, static_cast<int>(currItem->itemText.length()-1)); @@ -1153,6 +1191,19 @@ void ScribusMainWindow::setTBvals(PageItem *currItem) emit TextStyle(doc->currentStyle); // to go: (av) propertiesPalette->textPal->updateStyle(doc->currentStyle); + //check if mark in cursor place and enable editMark action + if (doc->appMode == modeEdit && currItem->itemText.cursorPosition() < currItem->itemText.length()) + { + ScText *hl = currItem->itemText.item(currItem->itemText.cursorPosition()); + if (hl->hasMark()) + { + scrActions["editMark"]->setEnabled(true); + if ((hl->mark->isType(MARKNoteMasterType) || hl->mark->isType(MARKNoteFrameType)) && (hl->mark->getNotePtr() != NULL)) + nsEditor->setNotesStyle(hl->mark->getNotePtr()->notesStyle()); + } + else + scrActions["editMark"]->setEnabled(false); + } } } @@ -1193,7 +1244,13 @@ void ScribusMainWindow::specialActionKeyEvent(const QString& actionName, int uni ss->set("ETEA", QString("insert_frametext")); ss->set("TEXT_STR", QString(QChar(unicodevalue))); ss->set("START", currItem->itemText.cursorPosition()); - undoManager->action(currItem, ss); + UndoObject * undoTarget = currItem; + if (currItem->isNoteFrame()) + { + undoTarget = doc; + ss->set("noteframeName", currItem->getUName()); + } + undoManager->action(undoTarget, ss); } } currItem->itemText.insertChars(QString(QChar(unicodevalue)), true); @@ -1226,7 +1283,13 @@ void ScribusMainWindow::specialActionKeyEvent(const QString& actionName, int uni ss->set("ETEA", QString("insert_frametext")); ss->set("TEXT_STR", QString(SpecialChars::SHYPHEN)); ss->set("START", currItem->itemText.cursorPosition()); - undoManager->action(currItem, ss); + UndoObject * undoTarget = currItem; + if (currItem->isNoteFrame()) + { + undoTarget = doc; + ss->set("noteframeName", currItem->getUName()); + } + undoManager->action(undoTarget, ss); } } currItem->itemText.insertChars(QString(SpecialChars::SHYPHEN), true); @@ -1597,16 +1660,25 @@ void ScribusMainWindow::keyPressEvent(QKeyEvent *k) if (currItem->asImageFrame() && !currItem->locked()) { currItem->handleModeEditKey(k, keyrep); - slotDocCh(false); } //FIXME:av view->oldCp = currItem->CPos; - else if (currItem->itemType() == PageItem::TextFrame) + if (currItem->itemType() == PageItem::TextFrame) { bool kr=keyrep; view->canvasMode()->keyPressEvent(k); //Hack for 1.4.x for stopping the cursor blinking while moving about currItem->handleModeEditKey(k, keyrep); + if (currItem->isAutoNoteFrame() && currItem->asNoteFrame()->notesList().isEmpty()) + { + if (!currItem->asNoteFrame()->isEndNotesFrame()) + { + currItem->asNoteFrame()->masterFrame()->invalidateLayout(); + currItem->asNoteFrame()->masterFrame()->updateLayout(); + } + } keyrep=kr; } + slotDocCh(false); + doc->regionsChanged()->update(QRectF()); } } } @@ -2038,6 +2110,8 @@ ScribusDoc *ScribusMainWindow::doFileNew(double width, double height, double top tempView->cmsToolbarButton->setChecked(tempDoc->HasCMS); undoManager->switchStack(tempDoc->DocName); styleManager->setDoc(tempDoc); + marksManager->setDoc(tempDoc); + nsEditor->setDoc(tempDoc); tocGenerator->setDoc(tempDoc); } undoManager->setUndoEnabled(true); @@ -2264,6 +2338,8 @@ void ScribusMainWindow::newActWin(QMdiSubWindow *w) docCheckerPalette->setDoc(doc); tocGenerator->setDoc(doc); styleManager->setDoc(doc); + marksManager->setDoc(doc); + nsEditor->setDoc(doc); symbolPalette->setDoc(doc); inlinePalette->setDoc(doc); modeToolBar->Angle->setValue(doc->itemToolPrefs().calligrapicPenAngle); @@ -2296,6 +2372,8 @@ void ScribusMainWindow::SwitchWin() updateActiveWindowCaption(doc->DocName); // scrActions["shade100"]->setChecked(true); propertiesPalette->setDoc(doc); + marksManager->setDoc(doc); + nsEditor->setDoc(doc); //propertiesPalette->Cpal->displayGradient(0); pagePalette->setView(view); layerPalette->setDoc(doc); @@ -2436,6 +2514,8 @@ void ScribusMainWindow::HaveNewDoc() // scrActions["editPatterns"]->setEnabled(true); // scrActions["editGradients"]->setEnabled(true); scrActions["editStyles"]->setEnabled(true); + scrActions["editMarks"]->setEnabled(true); + scrActions["editNotesStyles"]->setEnabled(true); scrActions["editMasterPages"]->setEnabled(true); scrActions["editJavascripts"]->setEnabled(true); @@ -2502,6 +2582,8 @@ void ScribusMainWindow::HaveNewDoc() updateActiveWindowCaption(doc->DocName); // scrActions["shade100"]->setChecked(true); propertiesPalette->setDoc(doc); + nsEditor->setDoc(doc); + marksManager->setDoc(doc); symbolPalette->setDoc(doc); inlinePalette->setDoc(doc); // propertiesPalette->Cpal->displayGradient(0); @@ -2861,6 +2943,8 @@ void ScribusMainWindow::HaveNewSel(int SelectedType) scrActions["toolsCopyProperties"]->setEnabled(true); scrActions["toolsEditWithStoryEditor"]->setEnabled(true); scrActions["insertSampleText"]->setEnabled(true); + scrMenuMgr->setMenuEnabled("InsertMark",true); + if ((currItem->nextInChain() != 0) || (currItem->prevInChain() != 0)) { scrActions["itemConvertToBezierCurve"]->setEnabled(false); @@ -2893,14 +2977,19 @@ void ScribusMainWindow::HaveNewSel(int SelectedType) setTBvals(currItem); scrActions["editSelectAll"]->setEnabled(true); scrActions["editSelectAllOnLayer"]->setEnabled(false); + scrMenuMgr->setMenuEnabled("InsertMark",true); charPalette->setEnabled(true, currItem); if (currItem->asTextFrame()) + { enableTextActions(&scrActions, true, currItem->currentStyle().charStyle().font().scName()); + currItem->asTextFrame()->togleEditModeActions(); + } view->horizRuler->setItem(currItem); view->horizRuler->update(); } else { + scrMenuMgr->setMenuEnabled("InsertMark",false); doc->currentStyle = currItem->itemText.defaultStyle(); propertiesPalette->textPal->displayParStyle(doc->currentStyle.parent()); propertiesPalette->textPal->displayCharStyle(doc->currentStyle.charStyle().parent()); @@ -3302,6 +3391,20 @@ void ScribusMainWindow::slotDocCh(bool /*reb*/) Q_ASSERT(plugin); // all the returned names should represent loaded plugins plugin->changedDoc(doc); } + if (m_marksCount != doc->marksList().count() || doc->notesChanged() || doc->flag_updateEndNotes || doc->flag_updateMarksLabels) + { + bool sendUpdateReqest = false; + if (m_marksCount != doc->marksList().count() || doc->flag_updateMarksLabels) + sendUpdateReqest = true; + m_marksCount = doc->marksList().count(); + doc->updateMarks(doc->notesChanged()); + doc->updateChangedEndNotesFrames(); + if (sendUpdateReqest) + emit UpdateRequest(reqMarksUpdate); + doc->setNotesChanged(false); + doc->flag_updateEndNotes = false; + doc->flag_updateMarksLabels = false; + } } void ScribusMainWindow::updateRecent(QString fn) @@ -4123,9 +4226,15 @@ bool ScribusMainWindow::loadDoc(QString fileName) for (int azz=0; azz<docItemsCount; ++azz) { PageItem *ite = doc->Items->at(azz); - if(ite->nextInChain() == NULL) + if((ite->nextInChain() == NULL) && !ite->isNoteFrame()) //do not layout notes frames ite->layout(); } + if (!doc->marksList().isEmpty()) + { + doc->setLoading(true); + doc->updateMarks(true); + doc->setLoading(false); + } for (QHash<int, PageItem*>::iterator itf = doc->FrameItems.begin(); itf != doc->FrameItems.end(); ++itf) { PageItem *ite = itf.value(); @@ -4192,6 +4301,8 @@ bool ScribusMainWindow::loadDoc(QString fileName) qApp->changeOverrideCursor(QCursor(Qt::ArrowCursor)); undoManager->setUndoEnabled(true); doc->setModified(false); + foreach (NotesStyle* NS, doc->m_docNotesStylesList) + doc->updateNotesFramesStyles(NS); #ifdef DEBUG_LOAD_TIMES times(&tms2); double ticks = sysconf(_SC_CLK_TCK); @@ -4270,6 +4381,8 @@ void ScribusMainWindow::slotGetContent() view->DrawNew(); slotDocCh(); styleManager->setDoc(doc); + marksManager->setDoc(doc); + nsEditor->setDoc(doc); } } } @@ -4682,6 +4795,8 @@ bool ScribusMainWindow::DoFileClose() // scrActions["editPatterns"]->setEnabled(false); // scrActions["editGradients"]->setEnabled(false); scrActions["editStyles"]->setEnabled(false); + scrActions["editMarks"]->setEnabled(false); + scrActions["editNotesStyles"]->setEnabled(false); scrActions["editSearchReplace"]->setEnabled(false); scrActions["editMasterPages"]->setEnabled(false); scrActions["editJavascripts"]->setEnabled(false); @@ -4789,6 +4904,8 @@ bool ScribusMainWindow::DoFileClose() charPalette->setDoc(0); tocGenerator->setDoc(0); styleManager->setDoc(0); + marksManager->setDoc(0); + nsEditor->setDoc(0); layerPalette->ClearInhalt(); docCheckerPalette->buildErrorList(0); HaveDoc--; @@ -5105,6 +5222,19 @@ void ScribusMainWindow::slotEditCopy() { if ((currItem->isSingleSel) && (currItem->isGroup())) return; + //do not copy notes frames + if (doc->m_Selection->count() ==1 && currItem->isNoteFrame()) + return; + //deselect notesframes + Selection tempSelection(*(doc->m_Selection)); + for (int i = 0; i < doc->m_Selection->count(); ++i) + { + if (doc->m_Selection->itemAt(i)->isNoteFrame()) + tempSelection.removeItem(doc->m_Selection->itemAt(i)); + } + if (tempSelection.count() < doc->m_Selection->count()) + *(doc->m_Selection) = tempSelection; + ScriXmlDoc ss; QString BufferS = ss.WriteElem(doc, doc->m_Selection); if (!internalCopy) @@ -5151,7 +5281,12 @@ void ScribusMainWindow::slotEditPaste() currItem = selItem->asTextFrame(); assert(currItem != NULL); if (currItem->HasSel) + { + //removing marks and notes from selected text +// if (currItem->isTextFrame() && !currItem->asTextFrame()->removeMarksFromText(!ScCore->usingGUI())) +// return; currItem->deleteSelectedTextFromFrame(); + } /*if (currItem->CPos < 0) currItem->CPos = 0; @@ -5168,6 +5303,18 @@ void ScribusMainWindow::slotEditPaste() textSerializer->parseMemory(xml, xml.length()); StoryText* story = textSerializer->result<StoryText>(); + + //avoid pasting notes marks into notes frames + if (currItem->isNoteFrame()) + { + story->setDoc(doc); + for (int pos=story->length() -1; pos >= 0; --pos) + { + ScText* hl = story->item(pos); + if (hl->hasMark() && (hl->mark->isNoteType())) + story->removeChars(pos,1); + } + } if (UndoManager::undoEnabled()) { ScItemState<StoryText> *is = new ScItemState<StoryText>(Um::Paste); @@ -5202,6 +5349,8 @@ void ScribusMainWindow::slotEditPaste() styleManager->setDoc(doc); propertiesPalette->unsetDoc(); propertiesPalette->setDoc(doc); + marksManager->setDoc(doc); + nsEditor->setDoc(doc); symbolPalette->unsetDoc(); symbolPalette->setDoc(doc); @@ -5296,6 +5445,8 @@ void ScribusMainWindow::slotEditPaste() styleManager->setDoc(doc); propertiesPalette->unsetDoc(); propertiesPalette->setDoc(doc); + marksManager->setDoc(doc); + nsEditor->setDoc(doc); symbolPalette->unsetDoc(); symbolPalette->setDoc(doc); inlinePalette->unsetDoc(); @@ -5338,6 +5489,8 @@ void ScribusMainWindow::slotEditPaste() delete activeTransaction; activeTransaction = NULL; } + if (doc->notesChanged()) + doc->notesFramesUpdate(); slotDocCh(false); } } @@ -5650,6 +5803,8 @@ void ScribusMainWindow::slotNewPageP(int wo, QString templ) doc->addPageToSection(wo, where, 1); else doc->addPageToSection(wo+1, where, 1); + + doc->updateEndnotesFrames(); doc->changed(); updateGUIAfterPagesChanged(); } @@ -5776,6 +5931,7 @@ void ScribusMainWindow::addNewPages(int wo, int where, int numPages, double heig doc->changed(); doc->addPageToSection(wo, where, numPages); doc->reformPages(); + doc->updateEndnotesFrames(); updateGUIAfterPagesChanged(); undoManager->setUndoEnabled(true); @@ -6600,13 +6756,17 @@ void ScribusMainWindow::setAppMode(int mode) // view->requestMode(modeEditClip); // return; // } - setTBvals(currItem); + //setTBvals before placing cursor has no effect currItem->itemText.setCursorPosition(0); + setTBvals(currItem); } scrActions["editPaste"]->setEnabled(false); charPalette->setEnabled(true, currItem); if (currItem!=NULL && currItem->asTextFrame()) + { enableTextActions(&scrActions, true, currItem->currentCharStyle().font().scName()); + currItem->asTextFrame()->togleEditModeActions(); + } if (ScMimeData::clipboardHasScribusData()) { bool textFrameEditMode = ((currItem != NULL) && (currItem->asTextFrame())); @@ -6650,6 +6810,9 @@ void ScribusMainWindow::setAppMode(int mode) // currItem->update(); } } + //disable text action which work only text frame in edit mode + if ((mode != modeEdit) || !currItem->isTextFrame()) + enableTextActions(&scrActions, false); int docSelectionCount=doc->m_Selection->count(); if (mode == modeDrawBezierLine) { @@ -6913,6 +7076,9 @@ void ScribusMainWindow::deletePage(int from, int to) for (int d = 0; d < doc->Items->count(); ++d) { ite = doc->Items->at(d); + //do not delete notes frames + if (ite->isAutoNoteFrame()) + continue; if (ite->OwnPage == a) { ite->setLocked(false); @@ -6964,6 +7130,7 @@ void ScribusMainWindow::deletePage(int from, int to) view->reformPagesView(); undoManager->setUndoEnabled(true); // ugly hack continues view->GotoPage(qMin(doc->Pages->count()-1, oldPg)); + doc->updateEndnotesFrames(); updateGUIAfterPagesChanged(); doc->rebuildMasterNames(); pagePalette->rebuildMasters(); @@ -6991,6 +7158,7 @@ void ScribusMainWindow::movePage() doc->movePage(from-1, to, wo-1, wie); updateGUIAfterPagesChanged(); } + doc->updateEndnotesFrames(); } delete dia; } @@ -7008,6 +7176,7 @@ void ScribusMainWindow::copyPage() int wo = dia->getWherePage(); doc->copyPage(pageNumberToCopy, wo, whereToInsert, copyCount); view->Deselect(true); + doc->updateEndnotesFrames(); updateGUIAfterPagesChanged(); slotDocCh(); } @@ -7045,6 +7214,7 @@ void ScribusMainWindow::changePageMargins() if (dia->masterPage() != Nam) Apply_MasterPage(dia->masterPage(), doc->currentPage()->pageNr()); } + doc->updateEndnotesFrames(); //CB: Moved to changePageMargins for #2338 //doc->currentPage()->marginPreset = dia->getMarginPreset(); //view->reformPages(dia->getMoveObjects()); @@ -7907,6 +8077,8 @@ int ScribusMainWindow::ShowSubs() inlinePalette->startup(); charPalette->startup(); styleManager->startup(); + marksManager->startup(); + nsEditor->startup(); symbolPalette->startup(); // init the toolbars @@ -10270,6 +10442,16 @@ void ScribusMainWindow::enableTextActions(QMap<QString, QPointer<ScrAction> > *a scrMenuMgr->setMenuEnabled("InsertQuote", enabled); scrMenuMgr->setMenuEnabled("InsertSpace", enabled); scrMenuMgr->setMenuEnabled("InsertLigature", enabled); + scrMenuMgr->setMenuEnabled("InsertMark", enabled); + if (!enabled) + { + scrActions["insertMarkVariableText"]->setEnabled(false); + scrActions["insertMarkAnchor"]->setEnabled(false); + scrActions["insertMarkItem"]->setEnabled(false); + scrActions["insertMark2Mark"]->setEnabled(false); + scrActions["insertMarkNote"]->setEnabled(false); + scrActions["editMark"]->setEnabled(false); + } } void ScribusMainWindow::updateGUIAfterPagesChanged() @@ -10321,3 +10503,625 @@ void ScribusMainWindow::updateTableMenuActions() scrActions["tableAdjustTableToFrame"]->setEnabled(table); } +void ScribusMainWindow::insertMark(MarkType mType) +{ + if (!HaveDoc) + return; + if (doc->m_Selection->count() != 1) + return; + if (doc->appMode != modeEdit) + return; + UndoTransaction* trans = NULL; + PageItem* currItem = doc->m_Selection->itemAt(0); + if (currItem->isTextFrame()) + { + if (currItem->HasSel) + { + if (UndoManager::instance()->undoEnabled()) + trans = new UndoTransaction(undoManager->beginTransaction(Um::Selection,Um::IDelete,Um::Delete,"",Um::IDelete)); + //inserting mark replace some selected text + currItem->asTextFrame()->deleteSelectedTextFromFrame(); + } + ScItemsState* is = NULL; + if (insertMarkDlg(currItem->asTextFrame(), mType, is)) + { + Mark* mrk = currItem->itemText.item(currItem->itemText.cursorPosition() -1)->mark; + view->updatesOn(false); + currItem->invalidateLayout(); + currItem->layout(); + if (mType == MARKNoteMasterType) + { + doc->setNotesChanged(true); + if (mrk->getNotePtr()->isEndNote()) + doc->flag_updateEndNotes = true; + doc->setCursor2MarkPos(mrk->getNotePtr()->noteMark()); + nsEditor->setNotesStyle(mrk->getNotePtr()->notesStyle()); + } + doc->changed(); + if (is != NULL) + is->set("label", mrk->label); + view->updatesOn(true); + view->DrawNew(); + } + if (trans) + { + trans->commit(); + delete trans; + trans = NULL; + } + } +} + +void ScribusMainWindow::slotEditMark() +{ + if (!HaveDoc) + return; + if (doc->m_Selection->count() != 1) + return; + if (doc->appMode != modeEdit) + return; + PageItem * currItem = doc->m_Selection->itemAt(0); + if (currItem->itemText.cursorPosition() < currItem->itemText.length()) + { + ScText *hl = currItem->itemText.item(currItem->itemText.cursorPosition()); + if (hl->hasMark()) + { + if (editMarkDlg(hl->mark, currItem->asTextFrame())) + { + if (hl->mark->isType(MARKVariableTextType)) + doc->flag_updateMarksLabels = true; + else + currItem->invalid = true; + //doc->updateMarks(); + doc->changed(); + doc->regionsChanged()->update(QRectF()); + view->DrawNew(); + } + if (hl->mark->isNoteType()) + nsEditor->setNotesStyle(hl->mark->getNotePtr()->notesStyle()); + } + } +} + +void ScribusMainWindow::slotUpdateMarks() +{ + if (!HaveDoc) + return; + if (doc->marksList().isEmpty()) + return; + if (doc->updateMarks(true)) + { + doc->changed(); + doc->regionsChanged()->update(QRectF()); + } +} + +void ScribusMainWindow::slotInsertMarkNote() +{ + if (doc->m_docNotesStylesList.count() == 1) + { //fast insert note with the only default notes style avaiable + PageItem* currItem = doc->m_Selection->itemAt(0); + Q_ASSERT(currItem->isTextFrame() && !currItem->isNoteFrame()); + UndoTransaction* trans = NULL; + if (currItem->HasSel) + { + if (UndoManager::instance()->undoEnabled()) + trans = new UndoTransaction(undoManager->beginTransaction(Um::Selection,Um::IDelete,Um::Delete,"",Um::IDelete)); + //inserting mark replace some selected text + currItem->asTextFrame()->deleteSelectedTextFromFrame(); + } + NotesStyle* nStyle = doc->m_docNotesStylesList.at(0); + QString label = "NoteMark_" + nStyle->name(); + if (nStyle->range() == NSRsection) + label += " in section " + doc->getSectionNameForPageIndex(currItem->OwnPage) + " page " + QString::number(currItem->OwnPage +1); + else if (nStyle->range() == NSRpage) + label += " on page " + QString::number(currItem->OwnPage +1); + else if (nStyle->range() == NSRstory) + label += " in " + currItem->firstInChain()->itemName(); + else if (nStyle->range() == NSRframe) + label += " in frame" + currItem->itemName(); + if (doc->getMarkDefinied(label + "_1", MARKNoteMasterType) != NULL) + getUniqueName(label,doc->marksLabelsList(MARKNoteMasterType), "_"); //FIX ME here user should be warned that inserted mark`s label was changed + else + label = label + "_1"; + Mark* mrk = doc->newMark(); + mrk->label = label; + mrk->setType(MARKNoteMasterType); + mrk->setNotePtr(doc->newNote(nStyle)); + mrk->getNotePtr()->setMasterMark(mrk); + mrk->setString(""); + mrk->OwnPage = currItem->OwnPage; + currItem->itemText.insertMark(mrk); + currItem->invalidateLayout(); + currItem->layout(); + if (mrk->getNotePtr()->isEndNote()) + doc->flag_updateEndNotes = true; + doc->regionsChanged()->update(QRectF()); + doc->changed(); + doc->setCursor2MarkPos(mrk->getNotePtr()->noteMark()); + if (UndoManager::undoEnabled()) + { + ScItemsState* is = new ScItemsState(UndoManager::InsertNote); + is->set("ETEA", mrk->label); + is->set("MARK", QString("new")); + is->set("label", mrk->label); + is->set("type", (int) MARKNoteMasterType); + is->set("strtxt", QString("")); + is->set("nStyle", nStyle->name()); + is->set("at", currItem->itemText.cursorPosition() -1); + is->insertItem("inItem", currItem); + undoManager->action(doc, is); + } + if (trans) + { + trans->commit(); + delete trans; + trans = NULL; + } + } + else + insertMark(MARKNoteMasterType); +} + +bool ScribusMainWindow::insertMarkDlg(PageItem_TextFrame* currItem, MarkType mrkType, ScItemsState* &is) +{ + if (doc->masterPageMode() && (mrkType != MARKVariableTextType)) + //avoid inserting in master pages other marks than Variable Text + return false; + + MarkInsertDlg* insertMDialog = NULL; + switch (mrkType) + { + case MARKAnchorType: + insertMDialog = (MarkInsertDlg*) new MarkAnchorDlg(this); + break; + case MARKVariableTextType: + insertMDialog = (MarkInsertDlg*) new MarkVariableTextDlg(doc->marksList(), this); + break; + case MARK2ItemType: + insertMDialog = (MarkInsertDlg*) new Mark2ItemDlg(this); + break; + case MARK2MarkType: + insertMDialog = (MarkInsertDlg*) new Mark2MarkDlg(doc->marksList(), NULL, this); + break; + case MARKNoteMasterType: + insertMDialog = (MarkInsertDlg*) new MarkNoteDlg(doc->m_docNotesStylesList, this); + break; + case MARKIndexType: + break; + default: + break; + } + if (insertMDialog == NULL) + { + qDebug() << "Dialog not implemented for such marks type " << mrkType; + return false; + } + bool docWasChanged = false; + + insertMDialog->setWindowTitle(tr("Insert new ") + insertMDialog->windowTitle()); + if (insertMDialog->exec()) + { + Mark* mrk = NULL; + Mark oldMark; + MarkData d; + if (currItem != NULL) + d.itemName = currItem->itemName(); + QString label = "", text = ""; + NotesStyle* NStyle = NULL; + bool insertExistedMark = false; + switch (mrkType) + { + case MARKAnchorType: + //only gets label for new mark + insertMDialog->values(label); + if (label.isEmpty()) + label = tr("Anchor mark"); + d.itemPtr = currItem; + break; + case MARKVariableTextType: + mrk = insertMDialog->values(label, text); + if ((mrk == NULL) && (text.isEmpty())) + return false; //FIX ME here user should be warned that inserting of mark fails and why + if (label.isEmpty()) + label = tr("Mark with <%1> variable text").arg(text); + d.strtxt = text; + break; + case MARK2ItemType: + insertMDialog->values(label, d.itemPtr); + if (d.itemPtr == NULL) + return false; //FIX ME here user should be warned that inserting of mark fails and why + if (label.isEmpty()) + label = tr("Mark to %1 item").arg(d.itemPtr->itemName()); + d.strtxt = QString::number(d.itemPtr->OwnPage +1); + break; + case MARK2MarkType: + //gets pointer to referenced mark + Mark* mrkPtr; + insertMDialog->values(label, mrkPtr); + if (mrkPtr == NULL) + return false; //FIX ME here user should be warned that inserting of mark fails and why + if (label.isEmpty()) + label = tr("Mark to %1 mark").arg(mrkPtr->label); + d.strtxt = QString::number(mrkPtr->OwnPage +1); + d.destmarkName = mrkPtr->label; + d.destmarkType = mrkPtr->getType(); + break; + case MARKNoteMasterType: + //gets pointer to choosed notes style + NStyle = insertMDialog->values(); + if (NStyle == NULL) + return false; + + d.notePtr = doc->newNote(NStyle); + label = "NoteMark_" + NStyle->name(); + if (NStyle->range() == NSRsection) + label += " in section " + doc->getSectionNameForPageIndex(currItem->OwnPage) + " page " + QString::number(currItem->OwnPage +1); + else if (NStyle->range() == NSRpage) + label += " on page " + QString::number(currItem->OwnPage +1); + else if (NStyle->range() == NSRstory) + label += " in " + currItem->firstInChain()->itemName(); + else if (NStyle->range() == NSRframe) + label += " in frame" + currItem->itemName(); + break; + case MARKIndexType: + return false; + break; + default: + return false; + break; + } + if (mrk == NULL) + { + //check if label for new mark can be used as is + if (mrkType == MARKNoteMasterType) + { + if (doc->getMarkDefinied(label + "_1", mrkType) != NULL) + getUniqueName(label,doc->marksLabelsList(mrkType), "_"); //FIX ME here user should be warned that inserted mark`s label was changed + else + label = label + "_1"; + } + else + getUniqueName(label,doc->marksLabelsList(mrkType), "_"); + mrk = doc->newMark(); + mrk->setValues(label, currItem->OwnPage, mrkType, d); + } + else + { // that must be variable text mark + oldMark = *mrk; + mrk->setString(d.strtxt); + mrk->label = label; + insertExistedMark = true; + doc->flag_updateMarksLabels = true; + } + + currItem->itemText.insertMark(mrk); + mrk->OwnPage = currItem->OwnPage; + + + if (mrkType == MARKNoteMasterType) + { + mrk->getNotePtr()->setMasterMark(mrk); + mrk->setString(""); + } + + if (UndoManager::undoEnabled()) + { + if (mrk->isType(MARKNoteMasterType)) + is = new ScItemsState(UndoManager::InsertNote); + else if (insertExistedMark && ((oldMark.label != mrk->label) || (oldMark.getString() != mrk->getString()))) + is = new ScItemsState(UndoManager::EditMark); + else + is = new ScItemsState(UndoManager::InsertMark); + is->set("ETEA", mrk->label); + is->set("label", mrk->label); + is->set("type", (int) mrk->getType()); + if (insertExistedMark) + { + is->set("MARK", QString("insert_existing")); + if (mrk->label != oldMark.label) + { + is->set("labelOLD", oldMark.label); + is->set("labelNEW", mrk->label); + doc->flag_updateMarksLabels = true; + } + if (oldMark.getString() != mrk->getString()) + { + is->set("strOLD", oldMark.getString()); + is->set("strNEW", mrk->getString()); + } + } + else + { + is->set("MARK", QString("new")); + is->set("strtxt", mrk->getString()); + if (mrk->isType(MARK2MarkType)) + { + QString dName; + MarkType dType; + mrk->getMark(dName, dType); + is->set("dName", dName); + is->set("dType", (int) dType); + } + if (mrk->isType(MARK2ItemType)) + is->insertItem("itemPtr", mrk->getItemPtr()); + if (mrk->isType(MARKNoteMasterType)) + is->set("nStyle", mrk->getNotePtr()->notesStyle()->name()); + } + is->set("at", currItem->itemText.cursorPosition() -1); + if (currItem->isNoteFrame()) + is->set("noteframeName", currItem->getUName()); + else + is->insertItem("inItem", currItem); + undoManager->action(doc, is); + docWasChanged = true; + } + } + delete insertMDialog; + return docWasChanged; +} + +bool ScribusMainWindow::editMarkDlg(Mark *mrk, PageItem_TextFrame* currItem) +{ + MarkInsertDlg* editMDialog = NULL; + switch (mrk->getType()) + { + case MARKAnchorType: + editMDialog = (MarkInsertDlg*) new MarkAnchorDlg(this); + editMDialog->setValues(mrk->label); + break; + case MARKVariableTextType: + if (currItem == NULL) + //invoked from Marks Manager + editMDialog = (MarkInsertDlg*) new MarkVariableTextDlg(mrk, this); + else + //invoked from mark`s entry in text + editMDialog = (MarkInsertDlg*) new MarkVariableTextDlg(doc->marksList(), this); + editMDialog->setValues(mrk->label, mrk->getString()); + break; + case MARK2ItemType: + editMDialog = (MarkInsertDlg*) new Mark2ItemDlg(this); + editMDialog->setValues(mrk->label, mrk->getItemPtr()); + break; + case MARK2MarkType: + { + editMDialog = (MarkInsertDlg*) new Mark2MarkDlg(doc->marksList(), mrk, this); + QString l; + MarkType t; + mrk->getMark(l,t); + Mark* m = doc->getMarkDefinied(l,t); + editMDialog->setValues(mrk->label, m); + } + break; + case MARKNoteMasterType: + { + //invoking editing note mark from master text + //so we go to edit note + TextNote* note = mrk->getNotePtr(); + if (note == NULL) + { + qFatal("ScribusMainWindow::editMarkDlg - found note master mark with null pointer to note"); + return false; + } + Mark* noteMark = note->noteMark(); + doc->setCursor2MarkPos(noteMark); + } + break; + case MARKNoteFrameType: + { + //invoking editing mark from note frame + //so we go to master text + TextNote* note = mrk->getNotePtr(); + if (note == NULL) + { + qFatal("ScribusMainWindow::editMarkDlg - found note frame mark with null pointer to note"); + return false; + } + Mark* masterMark = note->masterMark(); + doc->setCursor2MarkPos(masterMark); + } + case MARKIndexType: + return false; + break; + default: + break; + } + if (editMDialog == NULL) return false; + + bool docWasChanged = false; + + editMDialog->setWindowTitle(tr("Edit ") + editMDialog->windowTitle()); + if (editMDialog->exec()) + { + Mark oldMark = *mrk; + Mark* Mrk = NULL; + MarkData d; + if (currItem != NULL) + d.itemName = currItem->itemName(); + QString label = "", text = ""; + QString oldStr = mrk->getString(); + bool newMark = false; + bool replaceMark = false; + switch (mrk->getType()) + { + case MARKAnchorType: + //only gets label for new mark + editMDialog->values(label); + if (label.isEmpty()) + label = tr("Anchor mark"); + if (mrk->label != label) + { + getUniqueName(label,doc->marksLabelsList(mrk->getType()), "_"); //FIX ME here user should be warned that inserted mark`s label was changed + mrk->label = label; + } + break; + case MARKVariableTextType: + Mrk = editMDialog->values(label, text); + if (text.isEmpty()) + return false; //FIX ME here user should be warned that editing of mark fails and why + if (label.isEmpty()) + label = tr("Mark with <%1> variable text").arg(text); + if (Mrk != NULL) + { + if (Mrk != mrk) + { + ScText* hl = currItem->itemText.item(currItem->itemText.cursorPosition()); + hl->mark = Mrk; + mrk = Mrk; + oldMark = *mrk; + replaceMark = true; + } + if (mrk->label != label) + { + getUniqueName(label,doc->marksLabelsList(mrk->getType()), "_"); //FIX ME here user should be warned that inserted mark`s label was changed + mrk->label = label; + emit UpdateRequest(reqMarksUpdate); + } + if (text != oldStr) + { + mrk->setString(text); + docWasChanged = true; + } + } + else + { + d.strtxt = text; + mrk = doc->newMark(); + getUniqueName(label,doc->marksLabelsList(mrk->getType()), "_"); //FIX ME here user should be warned that inserted mark`s label was changed + mrk->setValues(label, currItem->OwnPage, MARKVariableTextType, d); + ScText* hl = currItem->itemText.item(currItem->itemText.cursorPosition()); + hl->mark = mrk; + docWasChanged = true; + newMark = true; + } + break; + case MARK2ItemType: + editMDialog->values(label, d.itemPtr); + if (d.itemPtr == NULL) + return false; //FIX ME here user should be warned that inserting of mark fails and why + if (label.isEmpty()) + label = tr("Mark to %1 item").arg(d.itemPtr->itemName()); + if (d.itemPtr != mrk->getItemPtr()) + { + mrk->setItemPtr(d.itemPtr); + mrk->setString(QString("%1").arg(d.itemPtr->OwnPage +1)); + docWasChanged = true; + } + if (mrk->label != label) + { + getUniqueName(label,doc->marksLabelsList(mrk->getType()), "_"); //FIX ME here user should be warned that inserted mark`s label was changed + mrk->label = label; + } + break; + case MARK2MarkType: + { + //gets pointer to referenced mark + Mark* mrkPtr = NULL; + editMDialog->values(label, mrkPtr); + if (mrkPtr == NULL) + return false; //FIX ME here user should be warned that inserting of mark fails and why + if (label.isEmpty()) + label = tr("Mark to %1 mark").arg(mrkPtr->label); + QString destLabel = mrkPtr->label; + MarkType destType = mrkPtr->getType(); + if (d.destmarkName != destLabel || d.destmarkType != destType) + { + mrk->setMark(mrkPtr); + mrk->setString(QString("%1").arg(mrkPtr->OwnPage +1)); + docWasChanged = true; + } + if (mrk->label != label) + { + getUniqueName(label,doc->marksLabelsList(mrk->getType()), "_"); //FIX ME here user should be warned that inserted mark`s label was changed + mrk->label = label; + } + } + break; + case MARKNoteMasterType: + break; + case MARKIndexType: + break; + default: + break; + } + if (UndoManager::undoEnabled()) + { + ScItemsState* is = NULL; + if (newMark || replaceMark) + is = new ScItemsState(UndoManager::InsertMark); + else + is = new ScItemsState(UndoManager::EditMark); + is->set("ETEA", mrk->label); + if (currItem != NULL) + { + is->set("at", currItem->itemText.cursorPosition()-1); + if (currItem->isNoteFrame()) + is->set("noteframeName", currItem->getUName()); + else + is->insertItem("inItem", currItem); + } + is->set("label", mrk->label); + is->set("type", (int) mrk->getType()); + is->set("strtxt", mrk->getString()); + if (newMark) + { + is->set("MARK", QString("new")); + if (mrk->isType(MARK2MarkType)) + { + QString dName; + MarkType dType; + mrk->getMark(dName, dType); + is->set("dName", dName); + is->set("dType", (int) dType); + } + if (mrk->isType(MARK2ItemType)) + is->insertItem("itemPtr", mrk->getItemPtr()); + if (mrk->isType(MARKNoteMasterType)) + is->set("nStyle", mrk->getNotePtr()->notesStyle()->name()); + doc->flag_updateMarksLabels = true; + } + else + { + if (replaceMark) + is->set("MARK", QString("replace")); + else + is->set("MARK", QString("edit")); + if (mrk->label != oldMark.label) + { + is->set("labelOLD", oldMark.label); + is->set("labelNEW", mrk->label); + doc->flag_updateMarksLabels = true; + } + if (mrk->getString() != oldMark.getString()) + { + is->set("strtxtOLD", oldMark.getString()); + is->set("strtxtNEW", mrk->getString()); + } + if (mrk->isType(MARK2MarkType)) + { + QString dNameOLD; + MarkType dTypeOLD; + oldMark.getMark(dNameOLD, dTypeOLD); + QString dName; + MarkType dType; + mrk->getMark(dName, dType); + if (dName != dNameOLD || dType != dTypeOLD) + { + is->set("dNameOLD", dNameOLD); + is->set("dTypeOLD", (int) dTypeOLD); + is->set("dNameNEW", dName); + is->set("dTypeNEW", (int) dType); + } + } + if (mrk->isType(MARK2ItemType) && mrk->getItemPtr() != oldMark.getItemPtr()) + { + is->insertItem("itemPtrOLD", oldMark.getItemPtr()); + is->insertItem("itemPtrNEW", mrk->getItemPtr()); + } + } + undoManager->action(doc, is); + } + } + delete editMDialog; + return docWasChanged; +} diff --git Scribus/scribus/scribus.h Scribus/scribus/scribus.h index e79d311..40657fa 100644 --- Scribus/scribus/scribus.h +++ Scribus/scribus/scribus.h @@ -75,10 +75,12 @@ class GuideManager; class HelpBrowser; class InlinePalette; class LayerPalette; +class MarksManager; class Measurements; class ScMWMenuManager; class ModeToolBar; class NodePalette; +class NotesStylesEditor; class OutlinePalette; class PDFToolBar; class PSLib; @@ -209,6 +211,8 @@ public: GuideManager *guidePalette; CharSelect *charPalette; PropertiesPalette *propertiesPalette; + MarksManager *marksManager; + NotesStylesEditor *nsEditor; NodePalette *nodePalette; OutlinePalette *outlinePalette; Biblio *scrapbookPalette; @@ -518,6 +522,7 @@ public slots: * canvas modes/gestures. */ void updateTableMenuActions(); + void emitUpdateRequest(int updateFlags) { emit UpdateRequest(updateFlags); } signals: void AppModeChanged(int oldMode, int newMode); @@ -610,6 +615,23 @@ private: FormatsManager *formatsManager; QPointer<HelpBrowser> helpBrowser; + +public slots: + //inserting marks + void slotInsertMark2Mark() { insertMark(MARK2MarkType); } + void slotInsertMarkAnchor() { insertMark(MARKAnchorType); } + void slotInsertMarkVariableText() { insertMark(MARKVariableTextType); } + void slotInsertMarkItem() { insertMark(MARK2ItemType); } + void slotInsertMarkNote(); + void slotInsertMarkIndex() { insertMark(MARKIndexType); } + void slotEditMark(); + //connected to signal emited by actions when "Update Marks" menu item is triggered + void slotUpdateMarks(); + bool editMarkDlg(Mark *mrk, PageItem_TextFrame* currItem = NULL); +private: + void insertMark(MarkType); + bool insertMarkDlg(PageItem_TextFrame* item, MarkType mT, ScItemsState* &is); + int m_marksCount; //remember marks count from last call }; #endif diff --git Scribus/scribus/scribusdoc.cpp Scribus/scribus/scribusdoc.cpp index 982ec38..c2ec1b0 100644 --- Scribus/scribus/scribusdoc.cpp +++ Scribus/scribus/scribusdoc.cpp @@ -53,6 +53,8 @@ for which a new license (GPL+exception) is in place. #include "hyphenator.h" #include "ui/inserttablecolumnsdialog.h" #include "ui/inserttablerowsdialog.h" +#include "notesstyles.h" +#include "ui/notesstyleseditor.h" #include "pageitem.h" #include "pageitem_imageframe.h" #include "pageitem_latexframe.h" @@ -62,6 +64,7 @@ for which a new license (GPL+exception) is in place. #include "pageitem_polyline.h" #include "pageitem_table.h" #include "pageitem_textframe.h" +#include "pageitem_noteframe.h" #ifdef HAVE_OSG #include "pageitem_osgframe.h" #endif @@ -103,6 +106,12 @@ for which a new license (GPL+exception) is in place. #include "colormgmt/sccolormgmtenginefactory.h" #include "ui/hruler.h" #include "ui/layers.h" +#include "ui/MarkInsertDlg.h" +#include "ui/mark2item.h" +#include "ui/mark2mark.h" +#include "ui/markanchor.h" +#include "ui/markvariabletext.h" +#include "ui/marksmanager.h" #include "ui/scmessagebox.h" #include "ui/storyeditor.h" @@ -261,7 +270,12 @@ ScribusDoc::ScribusDoc() : UndoObject( tr("Document")), Observable<ScribusDoc>(N m_alignTransaction(NULL), m_currentPage(NULL), m_updateManager(), - m_docUpdater(NULL) + m_docUpdater(NULL), + flag_notesChanged(false), + flag_restartMarksRenumbering(false), + flag_updateMarksLabels(false), + flag_updateEndNotes(false), + flag_layoutNotesFrames(true) { docUnitRatio=unitGetRatioFromIndex(docPrefsData.docSetupPrefs.docUnitIndex); docPrefsData.docSetupPrefs.pageHeight=0; @@ -356,7 +370,12 @@ ScribusDoc::ScribusDoc(const QString& docName, int unitindex, const PageSize& pa m_alignTransaction(NULL), m_currentPage(NULL), m_updateManager(), - m_docUpdater(NULL) + m_docUpdater(NULL), + flag_notesChanged(false), + flag_restartMarksRenumbering(false), + flag_updateMarksLabels(false), + flag_updateEndNotes(false), + flag_layoutNotesFrames(true) { docPrefsData.docSetupPrefs.docUnitIndex=unitindex; docPrefsData.docSetupPrefs.pageHeight=pagesize.height(); @@ -549,6 +568,9 @@ void ScribusDoc::init() m_masterPageMode=true; // quick hack to force the change of pointers in setMasterPageMode(); setMasterPageMode(false); addSymbols(); + //for loading old documents where default notes style is not saved + if (m_docNotesStylesList.isEmpty()) + m_docNotesStylesList.append(new NotesStyle()); } @@ -650,6 +672,13 @@ ScribusDoc::~ScribusDoc() delete pa.items.takeFirst(); } } + //deleting resources alocated for marks and notes + while (! m_docNotesList.isEmpty()) + delete m_docNotesList.takeFirst(); + while (!m_docMarksList.isEmpty()) + delete m_docMarksList.takeFirst(); + while (! m_docNotesStylesList.isEmpty()) + delete m_docNotesStylesList.takeFirst(); docPatterns.clear(); docGradients.clear(); while (!DocItems.isEmpty()) @@ -1255,6 +1284,15 @@ void ScribusDoc::replaceNamedResources(ResourceCollection& newNames) itemlist = NULL; } #endif + foreach (NotesStyle* nStyle, m_docNotesStylesList) + { //update styles names in notes styles + if (nStyle == NULL) + continue; + if (newNames.styles().contains(nStyle->notesParStyle())) + nStyle->setNotesParStyle(newNames.styles().value(nStyle->notesParStyle())); + if (newNames.charStyles().contains(nStyle->marksChStyle())) + nStyle->setMarksCharStyle(newNames.charStyles().value(nStyle->marksChStyle())); + } for (QHash<int, PageItem*>::iterator itf = FrameItems.begin(); itf != FrameItems.end(); ++itf) { PageItem *currItem = itf.value(); @@ -1799,6 +1837,412 @@ void ScribusDoc::restore(UndoState* state, bool isUndo) ss->get("NEW_PAGE_SIZE"), ss->getInt("NEW_PAGE_MARGINPRESET"), ss->getBool("OLD_PAGE_MOVEOBJECTS"), ss->getInt("PAGE_NUM"), ss->getInt("NEW_PAGE_TYPE")); } } + else if (ss->contains("DELETE_FRAMETEXT")) + { + PageItem * nF = getItemFromName(ss->get("noteframeName")); + Q_ASSERT(nF != NULL); + nF->asNoteFrame()->restoreDeleteNoteText(ss, isUndo); + } + else if (ss->contains("INSERT_FRAMETEXT")) + { + PageItem * nF = getItemFromName(ss->get("noteframeName")); + Q_ASSERT(nF != NULL); + nF->asNoteFrame()->restoreInsertNoteText(ss,isUndo); + } + else if (ss->contains("NSTYLE")) + { + NotesStyle* NS = NULL; + if ((ss->get("NSTYLE") == "new" && isUndo) || (ss->get("NSTYLE") == "delete" && !isUndo)) + deleteNotesStyle(ss->get("name")); + else if ((ss->get("NSTYLE") == "new" && !isUndo) || (ss->get("NSTYLE") == "delete" && isUndo)) + { + NS = new NotesStyle(); + NS->setName(ss->get("name")); + NS->setStart(ss->getInt("start")); + NS->setEndNotes(ss->getBool("endNotes")); + NS->setType((NumerationType) ss->getInt("numStyle")); + NS->setRange((NumerationRange) ss->getInt("range")); + NS->setPrefix(ss->get("prefix")); + NS->setSuffix(ss->get("suffix")); + NS->setAutoNotesHeight(ss->getBool("autoH")); + NS->setAutoNotesWidth(ss->getBool("autoW")); + NS->setAutoWeldNotesFrames(ss->getBool("autoWeld")); + NS->setAutoRemoveEmptyNotesFrames(ss->getBool("autoRemove")); + NS->setSuperscriptInMaster(ss->getBool("superMaster")); + NS->setSuperscriptInNote(ss->getBool("superNote")); + NS->setMarksCharStyle(ss->get("marksChStyle")); + NS->setNotesParStyle(ss->get("notesParStyle")); + m_docNotesStylesList.append(NS); + scMW()->emitUpdateRequest(reqMarksUpdate); + } + else if (ss->get("NSTYLE") == "edit") + { + if (isUndo) + NS = getNotesStyle(ss->get("NEWname")); + else + NS = getNotesStyle(ss->get("name")); + Q_ASSERT(NS != NULL); + //check if Notes Style change form footnotes to endnotes or range of numeration was changed + //if use delete all notes frames with current style + bool delNF = false; + if (ss->getBool("NEWendNotes") != ss->getBool("endNotes") + || ((isUndo && (ss->getBool("endNotes") && (NumerationRange) ss->getInt("range") != (NumerationRange) ss->getInt("NEWrange"))) + || (!isUndo && (ss->getBool("NEWendNotes") && ((NumerationRange) ss->getInt("NEWrange") != (NumerationRange) ss->getInt("range")))))) + delNF = true; + if (delNF) + { + foreach (PageItem_NoteFrame* nF, listNotesFrames(NS)) + delNoteFrame(nF, false); + flag_updateEndNotes = NS->isEndNotes(); + } + if (isUndo) + { + NS->setName(ss->get("name")); + NS->setStart(ss->getInt("start")); + NS->setRange((NumerationRange) ss->getInt("range")); + NS->setEndNotes(ss->getBool("endNotes")); + NS->setType((NumerationType) ss->getInt("numStyle")); + NS->setPrefix(ss->get("prefix")); + NS->setSuffix(ss->get("suffix")); + NS->setAutoNotesHeight(ss->getBool("autoH")); + NS->setAutoNotesWidth(ss->getBool("autoW")); + NS->setAutoWeldNotesFrames(ss->getBool("autoWeld")); + NS->setAutoRemoveEmptyNotesFrames(ss->getBool("autoRemove")); + NS->setSuperscriptInMaster(ss->getBool("superMaster")); + NS->setSuperscriptInNote(ss->getBool("superNote")); + NS->setMarksCharStyle(ss->get("marksChStyle")); + NS->setNotesParStyle(ss->get("notesParStyle")); + } + else + { + NS->setName(ss->get("NEWname")); + NS->setStart(ss->getInt("NEWstart")); + NS->setRange((NumerationRange) ss->getInt("NEWrange")); + NS->setEndNotes(ss->getBool("NEWendNotes")); + NS->setType((NumerationType) ss->getInt("NEWnumStyle")); + NS->setPrefix(ss->get("NEWprefix")); + NS->setSuffix(ss->get("NEWsuffix")); + NS->setAutoNotesHeight(ss->getBool("NEWautoH")); + NS->setAutoNotesWidth(ss->getBool("NEWautoW")); + NS->setAutoWeldNotesFrames(ss->getBool("NEWautoWeld")); + NS->setAutoRemoveEmptyNotesFrames(ss->getBool("NEWautoRemove")); + NS->setSuperscriptInMaster(ss->getBool("NEWsuperMaster")); + NS->setSuperscriptInNote(ss->getBool("NEWsuperNote")); + NS->setMarksCharStyle(ss->get("NEWmarksChStyle")); + NS->setNotesParStyle(ss->get("NEWnotesParStyle")); + } + setNotesChanged(true); + if ((ss->get("marksChStyle") != ss->get("NEWmarksChStyle")) + || (ss->getBool("superMaster") != ss->getBool("NEWsuperMaster"))) + invalidateMasterFrames(NS); + updateNotesNums(NS); + updateNotesFramesSettings(NS); + if (flag_updateEndNotes) + updateEndnotesFrames(NS, true); + updateNotesFramesStyles(NS); + if (notesChanged()) + { + flag_updateMarksLabels = true; + changed(); + regionsChanged()->update(QRectF()); + } + } + if (NS != NULL) + scMW()->nsEditor->setNotesStyle(NS); + else + scMW()->nsEditor->updateNSList(); + } + else if (ss->contains("DELETE_NOTE")) + { + ScItemsState *is = dynamic_cast<ScItemsState*>(state); + if (is) + { + NotesStyle* nStyle = getNotesStyle(is->get("nStyle")); + PageItem* master = NULL; + if (is->contains("noteframeName")) + master = getItemFromName(is->get("noteframeName")); + else + master = (PageItem*) is->getItem("inItem"); + if (isUndo) + { + TextNote* note = newNote(nStyle); + Mark* mrk = newMark(); + mrk->setType(MARKNoteMasterType); + mrk->setNotePtr(note); + note->setMasterMark(mrk); + note->setSaxedText(is->get("noteTXT")); + master->itemText.insertMark(mrk, is->getInt("at")); + master->invalid = true; + if (!nStyle->isAutoRemoveEmptyNotesFrames()) + { + PageItem_NoteFrame* nF = (PageItem_NoteFrame*) is->getItem("noteframe"); + Q_ASSERT(nF != NULL); + master->asTextFrame()->setNoteFrame(nF); + } + setNotesChanged(true); + if (note->isEndNote()) + flag_updateEndNotes = true; + } + else + { + TextNote* note = master->itemText.item(is->getInt("at"))->mark->getNotePtr(); + if (note->isEndNote()) + flag_updateEndNotes = true; + deleteNote(note); + } + master->invalidateLayout(); + master->updateLayout(); + } + } + else if (ss->contains("MARK")) + { + ScItemsState *is = dynamic_cast<ScItemsState*>(state); + if (is) + { + Mark* mrk = getMarkDefinied(is->get("label"), (MarkType) is->getInt("type")); + if (mrk == NULL && is->contains("labelOLD")) + mrk = getMarkDefinied(is->get("labelOLD"), (MarkType) is->getInt("type")); + int pos = is->getInt("at"); + bool isAutoNoteFrame = false; + PageItem* currItem = NULL; + if (is->contains("noteframeName")) + { + currItem = getItemFromName(is->get("noteframeName")); + if (currItem != NULL) + isAutoNoteFrame = currItem->asNoteFrame()->isAutoFrame(); + } + else + currItem = (PageItem*) is->getItem("inItem"); + if (isUndo) + { + if (is->get("MARK") == "new") + { + Q_ASSERT(mrk != NULL); + if (mrk->isNoteType()) + { + TextNote* note = mrk->getNotePtr(); + NotesStyle* nStyle = note->notesStyle(); + if (note->isEndNote()) + flag_updateEndNotes = true; + deleteNote(note); + updateNotesNums(nStyle); + } + else + eraseMark(mrk, true, currItem, true); + } + else if (is->get("MARK") == "replace") + { + Q_ASSERT(pos >= 0); + Q_ASSERT(currItem != NULL); + Q_ASSERT(mrk != NULL); + Mark* mrk = getMarkDefinied(is->get("label"), (MarkType) is->getInt("type")); + currItem->itemText.item(pos)->mark = mrk; + if (is->contains("strtxtOLD")) + { + mrk->setString(is->get("strtxtOLD")); + invalidateVariableTextFrames(mrk, false); + } + if (is->contains("labelOLD")) + mrk->label = is->get("labelOLD"); + } + else if (is->get("MARK") == "edit") + { + Q_ASSERT(mrk != NULL); + if (is->contains("labelOLD")) + mrk->label = is->get("labelOLD"); + if (is->contains("strtxtOLD")) + { + mrk->setString(is->get("strtxtOLD")); + invalidateVariableTextFrames(mrk, false); + } + if (is->contains("dNameOLD")) + mrk->setMark(is->get("dNameOLD"), (MarkType) is->getInt("dTypeOLD")); + if (is->getItem("itemPtrOLD") != NULL) + mrk->setItemPtr((PageItem*) is->getItem("itemPtrOLD")); + } + else if (is->get("MARK") == "insert_existing") + { + Q_ASSERT(pos >= 0); + Q_ASSERT(currItem != NULL); + Q_ASSERT(mrk != NULL); + currItem->itemText.removeChars(pos,1); + if (is->contains("strOLD")) + { + mrk->setString(is->get("strOLD")); + invalidateVariableTextFrames(mrk, false); + } + if (is->contains("labelOLD")) + mrk->label = is->get("labelOLD"); + } + else if (is->get("MARK") == "delete") + { + mrk = newMark(); + mrk->label = is->get("label"); + mrk->setType((MarkType) is->getInt("type")); + Q_ASSERT(pos >= 0); + Q_ASSERT(currItem != NULL); + currItem->itemText.insertMark(mrk, pos); + if (is->contains("strtxt")) + { + mrk->setString(is->get("strtxt")); + invalidateVariableTextFrames(mrk, false); + } + if (is->contains("dName")) + mrk->setMark(is->get("dName"), (MarkType) is->getInt("dType")); + if (is->getItem("itemPtr") != NULL) + mrk->setItemPtr((PageItem*) is->getItem("itemPtrOLD")); + } + else if (is->get("MARK") == "eraseFromText") ////for non-unique marks + { + Q_ASSERT(pos >= 0); + Q_ASSERT(mrk != NULL); + Q_ASSERT(currItem != NULL); + currItem->itemText.insertMark(mrk, pos); + if (is->contains("strNew")) + { + mrk->setString(is->get("strNEW")); + invalidateVariableTextFrames(mrk, false); + } + } + else if (is->get("MARK") == "delNonUnique") + { + //used if deleting non-unique marks by MarksManager + mrk = newMark(); + mrk->label = is->get("label"); + mrk->setType((MarkType) is->getInt("type")); + mrk->setString(is->get("strtxt")); + for (int i=0; i < is->insertItemPos.count(); ++i) + { + PageItem* item = (PageItem*) is->insertItemPos[i].first; + item->itemText.insertMark(mrk, is->insertItemPos[i].second); + item->invalid = true; + } + } + else + { + Q_ASSERT(false); + qDebug() << "MARK undo - unhandled " << is->get("MARK"); + } + } + else //REDO + { + if (is->get("MARK") == "new") + { + if (currItem == NULL) + { + qDebug() << "Wrong inItem in undo step for mark"; + return; + } + mrk = newMark(); + mrk->label = is->get("label"); + mrk->setType((MarkType) is->getInt("type")); + Q_ASSERT(currItem != NULL); + Q_ASSERT(pos >= 0); + currItem->itemText.insertMark(mrk, pos); + if (is->contains("strtxt")) + mrk->setString(is->get("strtxt")); + if (is->contains("dName")) + mrk->setMark(is->get("dName"), (MarkType) is->getInt("dType")); + if (is->getItem("itemPtr") != NULL) + mrk->setItemPtr((PageItem*) is->getItem("itemPtrOLD")); + if (mrk->isType(MARKNoteMasterType)) + { + NotesStyle* nStyle = getNotesStyle(is->get("nStyle"));; + TextNote* note = newNote(nStyle); + mrk->setNotePtr(note); + note->setMasterMark(mrk); + if (nStyle->isEndNotes()) + flag_updateEndNotes = true; + updateNotesNums(nStyle); + } + } + else if (is->get("MARK") == "replace") + { + Q_ASSERT(currItem != NULL); + Q_ASSERT(pos >= 0); + currItem->itemText.item(pos)->mark = getMarkDefinied(is->get("label"), (MarkType) is->getInt("type")); + if (is->contains("strtxtNEW")) + { + mrk->setString(is->get("strtxtNEW")); + invalidateVariableTextFrames(mrk, false); + } + if (is->contains("labelNEW")) + mrk->label = is->get("labelNEW"); + } + else if (is->get("MARK") == "edit") + { + if (is->contains("labelNEW")) + mrk->label = is->get("labelNEW"); + if (is->contains("strtxtNEW")) + { + mrk->setString(is->get("strtxtNEW")); + invalidateVariableTextFrames(mrk, false); + } + if (is->contains("dNameNEW")) + mrk->setMark(is->get("dNameNEW"), (MarkType) is->getInt("dTypeNEW")); + if (is->getItem("itemPtrNEW") != NULL) + mrk->setItemPtr((PageItem*) is->getItem("itemPtrNEW")); + } + else if (is->get("MARK") == "insert_existing") + { + Q_ASSERT(currItem != NULL); + Q_ASSERT(pos >= 0); + currItem->itemText.insertMark(mrk, pos); + if (is->contains("strNew")) + { + mrk->setString(is->get("strNEW")); + invalidateVariableTextFrames(mrk, false); + } + if (is->contains("labelNEW")) + mrk->label = is->get("labelNEW"); + } + else if (is->get("MARK") == "eraseFromText") //for non-unique marks + { + Q_ASSERT(currItem != NULL); + Q_ASSERT(pos >= 0); + currItem->itemText.removeChars(pos,1); + } + else if (is->get("MARK") == "delete") + { + if (!mrk->isUnique()) + { + Q_ASSERT(currItem != NULL); + Q_ASSERT(pos >= 0); + currItem->itemText.removeChars(pos,1); + } + else + { + if (mrk->isType(MARKNoteMasterType)) + { + TextNote* note = mrk->getNotePtr(); + NotesStyle* nStyle = note->notesStyle(); + if (note->isEndNote()) + flag_updateEndNotes = true; + deleteNote(note); + updateNotesNums(nStyle); + } + else + eraseMark(mrk, true); + } + } + else if (is->get("MARK") == "delNonUnique") + { + //used if deleting non-unique marks by MarksManager + eraseMark(mrk, true, NULL, true); + } + else + { + qDebug() << "MARK redo - unhandled " << is->get("MARK"); + } + } + scMW()->emitUpdateRequest(reqMarksUpdate); + if (currItem != NULL && !isAutoNoteFrame) + { + currItem->invalidateLayout(); + currItem->updateLayout(); + } + } + } if (layersUndo) { if (ScCore->usingGUI()) @@ -2352,6 +2796,7 @@ void ScribusDoc::movePage(const int fromPage, const int toPage, const int dest, m_View->reformPagesView(); m_ScMW->updateGUIAfterPagesChanged(); } + updateEndnotesFrames(); changed(); } @@ -2410,6 +2855,7 @@ int ScribusDoc::addAutomaticTextFrame(const int pageNumber) FirstAuto = Items->at(z); LastAuto = Items->at(z); Items->at(z)->setRedrawBounding(); + updateEndnotesFrames(); return z; } return -1; @@ -3963,22 +4409,12 @@ void ScribusDoc::getUsedFonts(QMap<QString, QMap<uint, FPointArray> > & Really) void ScribusDoc::checkItemForFonts(PageItem *it, QMap<QString, QMap<uint, FPointArray> > & Really, uint lc) { - FPointArray gly; - QChar chstr; - if (!it->isTextFrame() && !it->isPathText()) return; - /* May be needed for fixing #10371 completely - if (it->isAnnotation()) - { - int annotType = it->annotation().Type(); - bool mustEmbed = ((annotType >= 2) && (annotType <= 6) && (annotType != 4)); - if (mustEmbed && (!Really.contains(it->itemText.defaultStyle().charStyle().font().replacementName()))) - { - Really.insert(it->itemText.defaultStyle().charStyle().font().replacementName(), QMap<uint, FPointArray>()); - } - }*/ + FPointArray gly; + QChar chstr; + int start = it->isTextFrame() ? it->firstInFrame() : 0; int stop = it->isTextFrame() ? it->lastInFrame() + 1 : it->itemText.length(); for (int e = start; e < stop; ++e) @@ -4830,7 +5266,7 @@ bool ScribusDoc::copyPageToMasterPage(const int pageNumber, const int leftPage, return true; } -int ScribusDoc::itemAdd(const PageItem::ItemType itemType, const PageItem::ItemFrameType frameType, const double x, const double y, const double b, const double h, const double w, const QString& fill, const QString& outline, const bool itemFinalised) +int ScribusDoc::itemAdd(const PageItem::ItemType itemType, const PageItem::ItemFrameType frameType, const double x, const double y, const double b, const double h, const double w, const QString& fill, const QString& outline, const bool itemFinalised, const bool noteFrame) { assert(itemFinalised); // av: caller must wrap transaction around this if wanted UndoTransaction* activeTransaction = NULL; @@ -4848,6 +5284,9 @@ int ScribusDoc::itemAdd(const PageItem::ItemType itemType, const PageItem::ItemF Q_ASSERT(frameType==PageItem::Rectangle || frameType==PageItem::Unspecified); break; case PageItem::TextFrame: + if (noteFrame) + newItem = new PageItem_NoteFrame(this, x, y, b, h, w, CommonStrings::None, outline); + else newItem = new PageItem_TextFrame(this, x, y, b, h, w, CommonStrings::None, outline); Q_ASSERT(frameType==PageItem::Rectangle || frameType==PageItem::Unspecified); break; @@ -5855,7 +6294,6 @@ PageItem* ScribusDoc::convertItemTo(PageItem *currItem, PageItem::ItemType newTy { transactionConversion->cancel(); delete transactionConversion; - transactionConversion = NULL; } return NULL; } @@ -6422,6 +6860,17 @@ int ScribusDoc::getSectionKeyForPageIndex(const uint pageIndex) const return retVal; } +QString ScribusDoc::getSectionNameForPageIndex(const uint pageIndex) const +{ + DocumentSectionMap::ConstIterator it = docPrefsData.docSectionMap.begin(); + for (; it != docPrefsData.docSectionMap.end(); ++it) + { + if (pageIndex >= it.value().fromindex && pageIndex <= it.value().toindex) + return it.value().name; + } + return QString(); +} + const QString ScribusDoc::getSectionPageNumberForPageIndex(const uint pageIndex) const { @@ -7532,7 +7981,7 @@ void ScribusDoc::itemSelection_SetItemBrushShade(int sha) { UndoTransaction* activeTransaction = NULL; m_updateManager.setUpdatesDisabled(); - if (selectedItemCount > 1 && UndoManager::undoEnabled()) + if (UndoManager::undoEnabled() && selectedItemCount > 1) activeTransaction = new UndoTransaction(undoManager->beginTransaction(Um::SelectionGroup, Um::IGroup, Um::SetShade, QString("%1").arg(sha), Um::IShade)); @@ -8459,6 +8908,11 @@ void ScribusDoc::itemSelection_SetParagraphStyle(const ParagraphStyle & newStyle } else { + if (currItem->isNoteFrame()) + setNotesChanged(true); + else if (currItem->isTextFrame()) + updateItemNotesFramesStyles(currItem, newStyle); + else currItem->itemText.setDefaultStyle(newStyle); } if (currItem->asPathText()) @@ -8533,6 +8987,13 @@ void ScribusDoc::itemSelection_EraseParagraphStyle(Selection* customSelection) else { ParagraphStyle newStyle; + //for notes frames apply style from master frame + if (currItem->isNoteFrame() && (currItem->asNoteFrame()->masterFrame() != NULL)) + { + newStyle.setParent(currItem->asNoteFrame()->masterFrame()->itemText.defaultStyle().parent()); + newStyle.applyStyle(currItem->asNoteFrame()->masterFrame()->currentStyle()); + } + else newStyle.setParent(currItem->itemText.defaultStyle().parent()); if (UndoManager::undoEnabled()) { @@ -8542,10 +9003,18 @@ void ScribusDoc::itemSelection_EraseParagraphStyle(Selection* customSelection) undoManager->action(currItem, is); } currItem->itemText.setDefaultStyle(newStyle); + if (currItem->isTextFrame() && !currItem->isNoteFrame()) + updateItemNotesFramesStyles(currItem, newStyle); + else if (currItem->isNoteFrame()) + setNotesChanged(true); } currItem->invalid = true; if (currItem->asPathText()) currItem->updatePolyClip(); + if (currItem->isNoteFrame()) + currItem->asNoteFrame()->updateNotesText(); + else if (currItem->isTextFrame() && currItem->asTextFrame()->hasNoteFrame(NULL, true)) + setNotesChanged(true); } if (activeTransaction) { @@ -8583,6 +9052,10 @@ void ScribusDoc::itemSelection_ApplyParagraphStyle(const ParagraphStyle & newSty undoManager->action(currItem, is); } currItem->itemText.setDefaultStyle(dstyle); + if (currItem->isNoteFrame()) + setNotesChanged(true); + else if (currItem->isTextFrame()) + updateItemNotesFramesStyles(currItem, dstyle); } if (currItemTextCount > 0) { @@ -8623,6 +9096,10 @@ void ScribusDoc::itemSelection_ApplyParagraphStyle(const ParagraphStyle & newSty } if (currItem->asPathText()) currItem->updatePolyClip(); + if (currItem->isNoteFrame()) + currItem->asNoteFrame()->updateNotesText(); + else if (currItem->isTextFrame() && currItem->asTextFrame()->hasNoteFrame(NULL, true)) + setNotesChanged(true); currItem->invalidateLayout(); } if (activeTransaction) @@ -8746,9 +9223,15 @@ void ScribusDoc::itemSelection_ApplyCharStyle(const CharStyle & newStyle, Select // if (currItem->asPathText()) currItem->itemText.applyCharStyle(0, currItem->itemText.length(), newStyle); currItem->invalid = true; + if (currItem->isNoteFrame()) + setNotesChanged(true); + else if (currItem->isTextFrame()) + updateItemNotesFramesStyles(currItem, dstyle); } if (currItem->asPathText()) currItem->updatePolyClip(); + if (currItem->isNoteFrame()) + currItem->asNoteFrame()->updateNotesText(); currItem->invalidateLayout(); } if (activeTransaction) @@ -8828,9 +9311,15 @@ void ScribusDoc::itemSelection_SetCharStyle(const CharStyle & newStyle, Selectio currItem->itemText.setDefaultStyle(dstyle); // if (currItem->asPathText()) currItem->itemText.setCharStyle(0, currItem->itemText.length(), newStyle); + if (currItem->isNoteFrame()) + setNotesChanged(true); + else if (currItem->isTextFrame()) + updateItemNotesFramesStyles(currItem, dstyle); } if (currItem->asPathText()) currItem->updatePolyClip(); + if (currItem->isNoteFrame()) + currItem->asNoteFrame()->updateNotesText(); currItem->invalidateLayout(); } if (activeTransaction) @@ -8934,9 +9423,15 @@ void ScribusDoc::itemSelection_EraseCharStyle(Selection* customSelection) undoManager->action(currItem, is); } currItem->itemText.setDefaultStyle(defStyle); + if (currItem->isNoteFrame()) + setNotesChanged(true); + else if (currItem->isTextFrame()) + updateItemNotesFramesStyles(currItem, defStyle); } if (currItem->asPathText()) currItem->updatePolyClip(); + if (currItem->isNoteFrame()) + currItem->asNoteFrame()->updateNotesText(); currItem->invalidateLayout(); } if (activeTransaction) @@ -10104,7 +10599,9 @@ void ScribusDoc::itemSelection_Transform(int nrOfCopies, QTransform matrix, int // currItem->Frame = false; currItem->ClipEdited = true; // currItem->FrameType = 3; + undoManager->setUndoEnabled(false); AdjustItemSize(currItem); + undoManager->setUndoEnabled(true); } } else @@ -10183,7 +10680,6 @@ void ScribusDoc::itemSelection_Transform(int nrOfCopies, QTransform matrix, int state->setItem(l); undoManager->action(currItem, state); } - currItem->PoLine.translate(deltaX, deltaY); currItem->PoLine.map(matrixPre); currItem->PoLine.map(comulatedMatrix); @@ -10197,7 +10693,9 @@ void ScribusDoc::itemSelection_Transform(int nrOfCopies, QTransform matrix, int // currItem->Frame = false; currItem->ClipEdited = true; // currItem->FrameType = 3; + undoManager->setUndoEnabled(false); AdjustItemSize(currItem); + undoManager->setUndoEnabled(true); Elements.append(currItem); } comulatedMatrix *= matrix; @@ -10210,7 +10708,7 @@ void ScribusDoc::itemSelection_Transform(int nrOfCopies, QTransform matrix, int RotMode (rotBack); useRaster = savedAlignGrid; SnapGuides = savedAlignGuides; - SnapGuides = savedAlignElement; + SnapElement = savedAlignElement; DoDrawing = true; m_Selection->delaySignalsOff(); view()->updatesOn(true); @@ -10790,7 +11288,7 @@ void ScribusDoc::itemSelection_DeleteItem(Selection* customSelection, bool force selectedItemCount = delItems.count(); UndoTransaction* activeTransaction = NULL; - if ((selectedItemCount > 1) && UndoManager::undoEnabled()) + if (UndoManager::undoEnabled()) //always create transaction or check if item is reference for any mark or contains any mark or is welded etc activeTransaction = new UndoTransaction(undoManager->beginTransaction(Um::Group + "/" + Um::Selection, Um::IGroup, Um::Delete, tooltip, Um::IDelete)); @@ -10799,27 +11297,45 @@ void ScribusDoc::itemSelection_DeleteItem(Selection* customSelection, bool force currItem = delItems.at(selectedItemCount - (de + 1)); if ((currItem->asImageFrame()) && ((ScCore->fileWatcher->files().contains(currItem->Pfile) != 0) && (currItem->PictureIsAvailable))) ScCore->fileWatcher->removeFile(currItem->Pfile); - if (currItem->asTextFrame()) + //delete marks pointed to that item + for (int a=0; a < m_docMarksList.count(); a++) { - currItem->dropLinks(); - - /* this code will instead remove the contained text - // unlink after - currItem->unlink(); - if (before != 0) + Mark* m = m_docMarksList.at(a); + Q_ASSERT(m != NULL); + if (m->isType(MARK2ItemType) && (m->getItemPtr() == currItem)) + { + setUndoDelMark(m); + eraseMark(m, true, NULL, true); + } + } + if (currItem->isNoteFrame()) { - // unlink before - before->unlink(); - // repair link - if (after != 0) + if (currItem->itemText.length() >0) + { + currItem->itemText.selectAll(); + currItem->asTextFrame()->deleteSelectedTextFromFrame(); + if (currItem->asNoteFrame()->masterFrame()) + currItem->asNoteFrame()->masterFrame()->invalid = true; + } + if (!UndoManager::undoEnabled() || forceDeletion || currItem->isAutoNoteFrame()) { - before->link(after); + itemList->removeAll(currItem); + delNoteFrame(currItem->asNoteFrame(), false, false); + continue; } } - */ + else + { + if (currItem->asTextFrame()) + { + currItem->itemText.selectAll(); + currItem->asTextFrame()->removeMarksFromText(true); + currItem->asTextFrame()->delAllNoteFrames(false); + currItem->dropLinks(); } if (currItem->isWelded()) currItem->unWeld(); + } if (currItem->isBookmark) //CB From view emit DelBM(currItem); m_ScMW->DelBookMark(currItem); @@ -10833,7 +11349,7 @@ void ScribusDoc::itemSelection_DeleteItem(Selection* customSelection, bool force undoManager->action(Pages->at(0), is, currItem->getUPixmap()); } itemList->removeAll(currItem); -// if (forceDeletion || !UndoManager::undoEnabled()) +// undoManager->action(Pages->at(0), is, currItem->getUPixmap()); if (forceDeletion) delete currItem; } @@ -11267,14 +11783,17 @@ void ScribusDoc::itemSelection_SetImageScaleAndOffset(double sx, double sy, doub return; m_updateManager.setUpdatesDisabled(); UndoTransaction* outerTransaction = NULL; - if (UndoManager::undoEnabled()) + if (UndoManager::undoEnabled() && selectedItemCount > 1) outerTransaction = new UndoTransaction(undoManager->beginTransaction()); QString tooltip = Um::ItemsInvolved + "\n"; if (selectedItemCount > Um::ItemsInvolvedLimit) tooltip = Um::ItemsInvolved2 + "\n"; for (uint a = 0; a < selectedItemCount; ++a) { + UndoTransaction* activeTransaction = NULL; PageItem *currItem = itemSelection->itemAt(a); + if (UndoManager::undoEnabled()) + activeTransaction = new UndoTransaction(undoManager->beginTransaction()); currItem->setImageXYScale(sx, sy); currItem->setImageXYOffset(ox/sx, oy/sy); if (currItem->imageClip.size() != 0) @@ -11288,6 +11807,16 @@ void ScribusDoc::itemSelection_SetImageScaleAndOffset(double sx, double sy, doub } if (selectedItemCount <= Um::ItemsInvolvedLimit) tooltip += "\t" + currItem->getUName() + "\n"; + if (activeTransaction) + { + activeTransaction->commit(Um::Selection, + Um::IImageFrame, + Um::ImageScale, + tooltip, + Um::IImageScaling); + delete activeTransaction; + activeTransaction = NULL; + } currItem->update(); } if (outerTransaction) @@ -13264,7 +13793,6 @@ void ScribusDoc::getClosestElementBorder(double xin, double yin, double *xout, d } } - void ScribusDoc::SnapToGuides(PageItem *currItem) { int pg = OnPage(currItem); @@ -13569,6 +14097,7 @@ bool ScribusDoc::SizeItem(double newX, double newY, PageItem *pi, bool fromMP, b currItem->updateClip(); // currItem->updateGradientVectors(); } + if (activeTransaction) { currItem->checkChanges(); @@ -15024,7 +15553,7 @@ void NodeEditContext::finishTransaction(PageItem* currItem) if (nodeTransaction) // is there the old clip stored for the undo action { FPointArray newClip(Doc->nodeEdit.isContourLine ? currItem->ContourLine : currItem->PoLine); - if (*oldClip != newClip) + if (*oldClip != newClip && UndoManager::undoEnabled()) { QString name = Doc->nodeEdit.isContourLine ? Um::EditContour : Um::EditShape; ScItemState<QPair<FPointArray, FPointArray> > *state = @@ -15062,7 +15591,7 @@ ScItemState<QPair<FPointArray, FPointArray> >* NodeEditContext::finishTransactio if (nodeTransaction) // is there the old clip stored for the undo action { FPointArray newClip(Doc->nodeEdit.isContourLine ? currItem->ContourLine : currItem->PoLine); - if (*oldClip != newClip) + if (*oldClip != newClip && UndoManager::undoEnabled()) { QString name = Doc->nodeEdit.isContourLine ? Um::EditContour : Um::EditShape; state = new ScItemState<QPair<FPointArray, FPointArray> >(name); @@ -15772,17 +16301,13 @@ void ScribusDoc::itemSelection_UnlinkTextFrameWithText( Selection *customSelecti for (uint i = 0; i < selectedItemCount; ++i) { PageItem *currItem = itemSelection->itemAt(i); - if (currItem!=NULL) - { - if (currItem->asTextFrame() && (currItem->nextInChain() != NULL || currItem->prevInChain() != NULL)) + if (currItem != NULL && currItem->asTextFrame() && (currItem->nextInChain() != NULL || currItem->prevInChain() != NULL)) currItem->unlinkWithText(cutText); } - } regionsChanged()->update(QRectF()); changed(); itemSelection->itemAt(0)->emitAllToGUI(); } - } void ScribusDoc::itemSelection_UnlinkTextFrameWithTextCut( Selection *customSelection) @@ -15878,3 +16403,1352 @@ void ScribusDoc::itemResizeToMargin(PageItem* item, int direction) changed(); regionsChanged()->update(QRect()); } + +QStringList ScribusDoc::marksLabelsList(MarkType type) +{ + QStringList nameList; + for (int a=0; a < m_docMarksList.count(); ++a) + { + Mark* m = m_docMarksList.at(a); + if (m == NULL) + continue; + if ((m != NULL) && m->isType(type)) + nameList.append(m->label); + } + return nameList; +} + +Mark* ScribusDoc::getMarkDefinied(QString l, MarkType t) +{ + foreach (Mark* mrk, m_docMarksList) + { + if ((mrk != NULL) && (mrk->label == l) && mrk->isType(t)) + return mrk; + } + return NULL; +} + +Mark *ScribusDoc::newMark(Mark* mrk) +{ + Mark* newMrk = new Mark(); + if (mrk != NULL) + *newMrk = *mrk; + m_docMarksList.append(newMrk); + return newMrk; +} + +TextNote *ScribusDoc::newNote(NotesStyle* NS) +{ +// if (newNote == NULL) + TextNote* newNote = new TextNote(NS); + m_docNotesList.append(newNote); + setNotesChanged(true); + return newNote; +} + +PageItem* ScribusDoc::findMarkItem(Mark* mrk, int &lastItem) +{ + PageItem* item = NULL; + for (int a = lastItem +1; a < DocItems.count(); ++a) + { + item = DocItems.at(a); + if ((item != NULL) && item->isTextFrame() && (item->itemText.length() > 0)) + { + for (int i = item->firstInFrame(); i <= item->lastInFrame(); ++i) + { + ScText* hl = item->itemText.item(i); + if (hl->hasMark(mrk)) + { + lastItem = a; + return item; + } + } + } + } + lastItem = 0; + return NULL; +} + +int ScribusDoc::findMarkCPos(Mark* mrk, PageItem* &currItem, int Start) +{ + if (currItem == NULL) + currItem = findFirstMarkItem(mrk); + if (currItem == NULL) + return -1; + Q_ASSERT(currItem->isTextFrame()); + + if (Start < currItem->firstInFrame()) + Start = currItem->firstInFrame(); + + for (int i = Start; i < currItem->itemText.length(); ++i) + { + ScText* hl = currItem->itemText.item(i); + if (hl->hasMark(mrk)) + return i; + } + return -1; +} + +bool ScribusDoc::isMarkUsed(Mark* mrk, bool visible) +{ + foreach (PageItem* currItem, DocItems) + { + if (currItem->isTextFrame() && (currItem->itemText.length() > 0)) + { + if (!visible && currItem->prevInChain() != NULL) + //check in whole itemText only for first frames in chain + continue; + int i = 0; + int end = currItem->itemText.length(); + if (visible) + { + //search only in visible text + i = currItem->firstInFrame(); + end = currItem->lastInFrame() +1; + } + for (; i < end; ++i) + { + ScText* hl = currItem->itemText.item(i); + if (hl->hasMark(mrk)) + return true; + } + } + } + return false; +} + +void ScribusDoc::setCursor2MarkPos(Mark *mark) +{ + if (mark == NULL) + return; + PageItem* item = NULL; + if (mark->isType(MARKNoteFrameType) || mark->isType(MARKNoteMasterType)) + item = mark->getItemPtr(); + if (item == NULL) + item = getItemFromName(mark->getItemName()); + if (item == NULL) + item = findFirstMarkItem(mark); + if (item == NULL) + return; + + int CPos = findMarkCPos(mark, item); + if (CPos > -1) + { + scMW()->deselectAll(); + scMW()->selectItemFromOutlines(item, true, CPos +1); + } +} + +bool ScribusDoc::eraseMark(Mark *mrk, bool fromText, PageItem *item, bool force) +{ + bool found = false; + if (fromText) + { + if (item != NULL) + { + int MPos = findMarkCPos(mrk, item); + while (MPos > -1) + { + if (mrk->isType(MARKNoteFrameType) && MPos > 1 && item->itemText.text(MPos -1) == SpecialChars::PARSEP) + item->itemText.removeChars(MPos-1,2); + else + item->itemText.removeChars(MPos,1); + found = true; + MPos = findMarkCPos(mrk, item); + } + } + else + { + //find and delete all mark`s apperences in text + int MPos = -1; + int itemIndex = -1; + item = findMarkItem(mrk, itemIndex); + while (item != NULL) + { + MPos = findMarkCPos(mrk, item); + while (MPos > -1) + { + item->itemText.removeChars(MPos,1); + MPos = findMarkCPos(mrk, item); + } + found = true; + item->asTextFrame()->invalidateLayout(); + item = findMarkItem(mrk, itemIndex); + } + } + } + //remove mark references + for (int a=0; a < m_docMarksList.count(); ++a) + { + Mark* m = m_docMarksList.at(a); + if (m == NULL) + continue; + if (m->isType(MARK2MarkType)) + { + QString l; + MarkType t; + m->getMark(l, t); + if (mrk == getMarkDefinied(l, t)) + { + setUndoDelMark(m); + eraseMark(m, true, NULL, true); + } + } + } + //erase mark from marksMap + if (mrk->isUnique() || force) + { + m_docMarksList.removeOne(mrk); + delete mrk; + } + return found; +} + +void ScribusDoc::setUndoDelMark(Mark *mrk) +{ //used by MarksManager + if (UndoManager::undoEnabled()) + { + ScItemsState* ims = new ScItemsState(Um::DeleteMark,"",Um::IDelete); + if (mrk->isUnique()) + { + ims->set("MARK", QString("delete")); + PageItem* master = findFirstMarkItem(mrk); + if (master->isNoteFrame()) + ims->set("noteframeName", master->getUName()); + else + ims->insertItem("inItem", master); + ims->set("at", findMarkCPos(mrk, master)); + if (mrk->isType(MARK2MarkType)) + { + QString dName; + MarkType dType; + mrk->getMark(dName, dType); + ims->set("dName", dName); + ims->set("dType", (int) dType); + } + if (mrk->isType(MARK2ItemType)) + ims->insertItem("itemPtr", mrk->getItemPtr()); + } + else + { + ims->set("MARK", QString("delNonUnique")); + int MPos = -1; + int itemIndex = -1; + //find all mark insertions + PageItem* item = findMarkItem(mrk, itemIndex); + while (item != NULL) + { + int num = 0; //shift of insertion position for undo + MPos = findMarkCPos(mrk, item); + while (MPos > -1) + { + ims->insertItemPos.append(QPair<void*, int>((void*) item, MPos - num)); //-num as while undo text will be shorter (without marks) + //++num; + MPos = findMarkCPos(mrk, item, MPos+1); + } + item = findMarkItem(mrk, itemIndex); + } + } + ims->set("ETEA", mrk->label); + ims->set("label", mrk->label); + ims->set("type", (int) mrk->getType()); + ims->set("strtxt", mrk->getString()); + undoManager->action(this, ims); + } +} + +bool ScribusDoc::invalidateVariableTextFrames(Mark* mrk, bool forceUpdate) +{ + if (!mrk->isType(MARKVariableTextType)) + return false; + int itemNo = -1; + bool found = false; + PageItem* mItem = findMarkItem(mrk, itemNo); + while (mItem != NULL) + { + found = true; + mItem->asTextFrame()->invalidateLayout(); + if (forceUpdate) + mItem->layout(); + mItem = findMarkItem(mrk, itemNo); + } + return found; +} + +//update strings (page number) for marks pointed to anchors and items +//and update marks list in Marka Manager +bool ScribusDoc::updateMarks(bool updateNotesMarks) +{ + if (m_docMarksList.isEmpty()) + { + if ((!notesList().isEmpty() || notesChanged()) && updateNotesMarks && !isLoading()) + return notesFramesUpdate(); + return false; + } + Q_ASSERT(m_docMarksList.removeAll(NULL) == 0); + + bool docWasChanged = false; + + if (!isLoading()) + { + //run for variable text (invalidate frames with variable text) + foreach (Mark* mrk, m_docMarksList) + { + if (mrk->isType(MARKVariableTextType)) + { + if (invalidateVariableTextFrames(mrk, false)) + docWasChanged = true; + } + else if (mrk->isUnique()) + { + PageItem* mItem = findFirstMarkItem(mrk); + mrk->OwnPage =(mItem != NULL) ? mItem->OwnPage : -1; + mrk->setItemName((mItem != NULL) ? mItem->itemName() : ""); + } + } + } + + //update marks for foot/endnotes + if (updateNotesMarks) + { + //update notes numbers + for (int i=0; i < m_docNotesStylesList.count(); ++i) + { + NotesStyle* NS = m_docNotesStylesList.at(i); + //update nums + if (updateNotesNums(NS)) + { + //refresh endnotes content + if (flag_updateEndNotes || isLoading()) + updateEndnotesFrames(NS); + docWasChanged = true; + } + if (flag_updateEndNotes) + updateEndnotesFrames(NS); + updateNotesFramesStyles(NS); + } + docWasChanged = notesFramesUpdate(); + } + + //for all marks + foreach (Mark* mrk, m_docMarksList) + { + //set mark page number + PageItem* mItem = findFirstMarkItem(mrk); + if (mItem != NULL) + mrk->OwnPage = mItem->OwnPage; + else + mrk->OwnPage = -1; + if (mrk->isType(MARK2ItemType)) + { + if (mrk->getItemPtr() != NULL) + { + int page = mrk->getItemPtr()->OwnPage +1; + if (mrk->getString().toInt() != page) + { + mrk->setString(QString("%1").arg(page)); + if (mItem != NULL) + { + mItem->asTextFrame()->invalidateLayout(); + docWasChanged = true; + } + } + } + else + mrk->setString(""); + } + else if (mrk->isType(MARK2MarkType)) + { + QString l; + MarkType t; + mrk->getMark(l,t); + Mark* destMark = getMarkDefinied(l,t); + if (destMark != NULL) + { + PageItem* dItem = findFirstMarkItem(destMark); + if (dItem == NULL) + { + destMark->OwnPage = -1; + mrk->setString(""); + docWasChanged = true; + } + else + { + destMark->OwnPage = dItem->OwnPage; + int page = destMark->OwnPage +1; + if (mrk->getString().toInt() != page) + { + mrk->setString(QString("%1").arg(page)); + if (mItem != NULL) + { + mItem->asTextFrame()->invalidateLayout(); + docWasChanged = true; + } + } + } + } + else + { + mrk->setString(""); + docWasChanged = true; + } + } + } + return docWasChanged; +} + +NotesStyle* ScribusDoc::newNotesStyle(NotesStyle NS) +{ + QString nsName = NS.name(); + + //if doc is loading overwrite current set + NotesStyle* newNS = getNotesStyle(nsName); + if (isLoading() && (newNS != NULL)) + *newNS = NS; + else + { + //add new notes style + if (!validateNSet(NS)) + return NULL; + newNS = new NotesStyle(); + *newNS = NS; + QStringList nsNames; + for (int a = 0; a< m_docNotesStylesList.count(); ++a) + nsNames.append(m_docNotesStylesList.at(a)->name()); + getUniqueName(nsName, nsNames, "_"); + newNS->setName(nsName); + m_docNotesStylesList.append(newNS); + if (undoManager->undoEnabled()) + { + SimpleState* ss = new SimpleState(UndoManager::NewNotesStyle); + ss->set("NSTYLE", QString("new")); + undoSetNotesStyle(ss, newNS); + undoManager->action(this, ss); + } + } + return newNS; +} + +void ScribusDoc::renameNotesStyle(NotesStyle* NS, QString newName) +{ + foreach (Mark* mrk, m_docMarksList) + mrk->label.replace("_" + NS->name()+ "_", "_" + newName + "_"); + NS->setName(newName); +} + +void ScribusDoc::deleteNotesStyle(QString nsName) +{ + NotesStyle* NS = getNotesStyle(nsName); + assert(NS != NULL); + //do not delete default notes style + if (NS == m_docNotesStylesList.at(0)) + return; + UndoTransaction* activeTransaction = NULL; + if (UndoManager::instance()->undoEnabled()) + activeTransaction = new UndoTransaction(undoManager->beginTransaction(Um::DeleteNotesStyle,Um::IDelete,Um::Delete,"",Um::IDelete)); + QList<TextNote*> toDel; + //search for notes to deleting + foreach (TextNote* note, m_docNotesList) + { + if (note->notesStyle() == NS) + toDel.append(note); + } + //deleting notes + QList<PageItem*> master2Update; + if (!toDel.isEmpty()) + { + while (!toDel.isEmpty()) + { + TextNote* note = toDel.takeFirst(); + master2Update.append(findFirstMarkItem(note->masterMark())); + setUndoDelNote(note); + deleteNote(note); + } + while (!master2Update.isEmpty()) + master2Update.takeFirst()->layout(); + } + if (activeTransaction) + { + //undo is enabled + SimpleState* ss = new SimpleState(UndoManager::DeleteNotesStyle); + ss->set("NSTYLE", QString("delete")); + undoSetNotesStyle(ss, NS); + undoManager->action(this, ss); + + activeTransaction->commit(); + delete activeTransaction; + activeTransaction = NULL; + } + flag_updateMarksLabels = true; + if (NS->isEndNotes()) + flag_updateEndNotes = true; + notesFramesUpdate(); + m_docNotesStylesList.removeOne(NS); + scMW()->emitUpdateRequest(reqMarksUpdate); + delete NS; +} + +void ScribusDoc::undoSetNotesStyle(SimpleState* ss, NotesStyle *NS) +{ + ss->set("name", NS->name()); + ss->set("start", NS->start()); + ss->set("endNotes", NS->isEndNotes()); + ss->set("numStyle", (int) NS->getType()); + ss->set("range", (int) NS->range()); + ss->set("prefix", NS->prefix()); + ss->set("suffix", NS->suffix()); + ss->set("autoH", NS->isAutoNotesHeight()); + ss->set("autoW", NS->isAutoNotesWidth()); + ss->set("autoWeld", NS->isAutoWeldNotesFrames()); + ss->set("autoRemove", NS->isAutoRemoveEmptyNotesFrames()); + ss->set("superMaster", NS->isSuperscriptInMaster()); + ss->set("superNote", NS->isSuperscriptInNote()); + ss->set("marksChStyle", NS->marksChStyle()); + ss->set("notesParStyle", NS->notesParStyle()); +} + +NotesStyle* ScribusDoc::getNotesStyle(QString nsName) +{ + for (int a=0; a < m_docNotesStylesList.count(); ++a) + { + if (m_docNotesStylesList.at(a)->name() == nsName) + return m_docNotesStylesList.at(a); + } + return NULL; +} + +void ScribusDoc::deleteNote(TextNote* note) +{ + if (note == NULL) + return; + PageItem_NoteFrame* nF = NULL; + if (note->noteMark() != NULL) + if (note->noteMark()->getItemPtr() != NULL) + nF = note->noteMark()->getItemPtr()->asNoteFrame(); + if (nF == NULL) + nF = findFirstMarkItem(note->noteMark())->asNoteFrame(); + Q_ASSERT(nF != NULL); + nF->removeNote(note); + PageItem* master = note->masterMark()->getItemPtr(); + nF->invalid = true; + master->invalid = true; + if (nF->notesList().isEmpty() && nF->isAutoNoteFrame()) + { + nF->deleteIt = true; + master->asTextFrame()->removeNoteFrame(nF); + } +// else +// master->asTextFrame()->setNoteFrame(nF); + if (note->masterMark() != NULL) + eraseMark(note->masterMark(), true, master); + if (note->noteMark() != NULL) + eraseMark(note->noteMark(), true, nF); + m_docNotesList.removeOne(note); + setNotesChanged(true); + if (note->isEndNote()) + flag_updateEndNotes = true; + delete note; +} + +void ScribusDoc::setUndoDelNote(TextNote *note) +{ //used by MarksManager + if (UndoManager::undoEnabled()) + { + ScItemsState* ims = new ScItemsState(Um::DeleteNote,"",Um::IDelete); + ims->set("DELETE_NOTE", QString("delete_note")); + ims->set("ETEA", note->masterMark()->label); + PageItem* master = note->masterMark()->getItemPtr(); + int pos = findMarkCPos(note->masterMark(), master); + Q_ASSERT(pos > -1); + Q_ASSERT(master); + ims->insertItem("inItem", master); + ims->set("at", pos); + ims->set("noteTXT", note->saxedText()); + ims->set("nStyle", note->notesStyle()->name()); + if (!note->notesStyle()->isAutoRemoveEmptyNotesFrames()) + ims->insertItem("noteframe", note->noteMark()->getItemPtr()); + undoManager->action(this, ims); + } +} + +void ScribusDoc::updateItemNotesNums(PageItem_TextFrame* frame, NotesStyle* nStyle, int &num) +{ + //update marks strings in master text and in notes frame (only numbers!) + //check if notes schould be added or removed from notes frame + int noteNum = num; + ScText* hl; + int index = 0; + bool doUpdate = false; + + for (int pos = frame->firstInFrame(); pos <= frame->lastInFrame(); ++pos) + { + hl = frame->itemText.item(pos); + if (hl->hasMark() && hl->mark->isType(MARKNoteMasterType)) + { + if (hl->mark->getNotePtr() == NULL) + continue; + if (hl->mark->getNotePtr()->notesStyle() == nStyle) + { + QString numStr = nStyle->prefix() + nStyle->numString(noteNum) + nStyle->suffix(); + QString mStr = hl->mark->getString(); + QString label = hl->mark->label; + if ((mStr != numStr) || flag_updateMarksLabels || flag_updateEndNotes) + { + doUpdate = true; + hl->mark->setString(numStr); + label = "NoteMark_" + nStyle->name(); + if (nStyle->range() != NSRdocument) + { + if (nStyle->range() == NSRsection) + label += " in section " + getSectionNameForPageIndex(frame->OwnPage) + " page " + QString::number(frame->OwnPage +1); + else if (nStyle->range() == NSRpage) + label += " on page " + QString::number(frame->OwnPage +1); + else if (nStyle->range() == NSRstory) + label += " in " + frame->firstInChain()->itemName(); + else if (nStyle->range() == NSRframe) + label += " in frame " + frame->itemName(); + } + label += "_" + QString::number(noteNum); + hl->mark->label = label; + } + TextNote* note = hl->mark->getNotePtr(); + note->setNum(noteNum); + note->masterMark()->setItemPtr(frame); + if (note->noteMark() != NULL) + { + note->noteMark()->setString(numStr); + label = label.replace("NoteMark","NoteFrameMark"); + note->noteMark()->label = label; + } + ++index; + ++noteNum; + } + } + } + PageItem_NoteFrame * nF; + if (nStyle->isEndNotes()) + nF = endNoteFrame(nStyle); + else + nF = frame->itemNoteFrame(nStyle); + + if (doUpdate) + { + frame->invalidateLayout(); + if ((nF != NULL) && !nF->deleteIt) + { + if (nStyle->isEndNotes()) + m_docEndNotesFramesChanged.append(nF); + else + nF->invalidateLayout(true); + } + } + num = noteNum; + if (!nStyle->isEndNotes() && (index == 0) && (nF != NULL) && nF->isAutoNoteFrame()) + nF->deleteIt = true; +} + +bool ScribusDoc::updateNotesNums(NotesStyle *nStyle) +{ + bool docWasChanged = false; + flag_restartMarksRenumbering = false; + flag_updateEndNotes = false; + PageItem_NoteFrame* endNF = NULL; + if (nStyle->isEndNotes() && nStyle->range() == NSRdocument) + { + endNF = endNoteFrame(nStyle); + if (endNF != NULL) + clearNotesInFrameList(endNF); + } + flag_layoutNotesFrames = false; //do not layout notes frames while counting notes + int num, i; + int itemsCount = Items->count(); + if ((nStyle->range() == NSRdocument) || ((nStyle->range() == NSRsection) && docPrefsData.docSectionMap.isEmpty())) + { + //FIX ME: how to change frames order on page? and what about reverse page order? + num = nStyle->start(); + for (int page = 0; page < Pages->count(); ++page) + { + for (i = 0; i < itemsCount; ++i) + { + PageItem* currItem = Items->at(i); + if ((currItem->OwnPage == page) && currItem->isTextFrame() && !currItem->isNoteFrame() && (currItem->itemText.length() > 0)) + { + if (!currItem->asTextFrame()->isValidChainFromBegin()) + { + currItem->layout(); + if (flag_restartMarksRenumbering) + { + //restart whole update as items was changed + if (endNF != NULL) + clearNotesInFrameList(endNF); + page = -1; + i = -1; + itemsCount = Items->count(); + num = nStyle->start(); + docWasChanged = true; + flag_restartMarksRenumbering = false; + break; + } + } + if (nStyle->isEndNotes() || currItem->asTextFrame()->hasNoteFrame(nStyle, false)) + updateItemNotesNums(currItem->asTextFrame(), nStyle, num); + if (currItem->asTextFrame()->hasNoteFrame(nStyle, false) && currItem->asTextFrame()->itemNoteFrame(nStyle)->invalid) + docWasChanged = true; + if (currItem->invalid) + { + currItem->layout(); + docWasChanged = true; + } + } + } + } + if ((num == nStyle->start()) && nStyle->isEndNotes()) + { + PageItem_NoteFrame* nF = endNoteFrame(nStyle); + if (nF != NULL && nF->isAutoNoteFrame()) + nF->deleteIt = true; + } + } + else if (nStyle->range() == NSRsection) + { + Q_ASSERT(!docPrefsData.docSectionMap.isEmpty()); + foreach (DocumentSection section, docPrefsData.docSectionMap.values()) + { + num = nStyle->start(); + for (int page = section.fromindex; page <= (int) section.toindex ; ++page) + { + if (nStyle->isEndNotes()) + { + endNF = endNoteFrame(nStyle, getSectionKeyForPageIndex(page)); + if (endNF != NULL) + clearNotesInFrameList(endNF); + } + for (i = 0; i < itemsCount; ++i) + { + PageItem* currItem = Items->at(i); + if (currItem == NULL) + continue; + if ((currItem->OwnPage == page) && currItem->isTextFrame() && !currItem->isNoteFrame() && (currItem->itemText.length() > 0)) + { + if (!currItem->asTextFrame()->isValidChainFromBegin()) + { + currItem->layout(); + if (flag_restartMarksRenumbering) + { + //restart whole update as items was changed + if (endNF != NULL) + clearNotesInFrameList(endNF); + page = section.fromindex -1; + i = -1; + itemsCount = Items->count(); + num = nStyle->start(); + docWasChanged = true; + flag_restartMarksRenumbering = false; + break; + } + } + if (nStyle->isEndNotes() || currItem->asTextFrame()->hasNoteFrame(nStyle, false)) + updateItemNotesNums(currItem->asTextFrame(), nStyle, num); + if (currItem->asTextFrame()->hasNoteFrame(nStyle, false) && currItem->asTextFrame()->itemNoteFrame(nStyle)->invalid) + docWasChanged = true; + if (currItem->invalid) + { + currItem->layout(); + docWasChanged = true; + } + } + } + if ((i != -1) && (num == nStyle->start()) && nStyle->isEndNotes()) + { + PageItem_NoteFrame* nF = endNoteFrame(nStyle); + if (nF != NULL && nF->isAutoNoteFrame()) + nF->deleteIt = true; + } + } + } + } + else if (nStyle->range() == NSRstory || nStyle->range() == NSRframe) + { + for (i = 0; i < itemsCount; ++i) + { + PageItem* currItem = Items->at(i); + if (currItem == NULL) + continue; + if (currItem->isTextFrame() && !currItem->isNoteFrame() && (currItem->itemText.length() > 0)) + { + if (nStyle->isEndNotes() && nStyle->range() == NSRstory) + { + endNF = endNoteFrame(nStyle, (void*) currItem); + if (endNF != NULL) + clearNotesInFrameList(endNF); + } + if (!currItem->asTextFrame()->isValidChainFromBegin()) + { + currItem->layout(); + if (flag_restartMarksRenumbering) + { + //restart whole update as items was changed + if (endNF != NULL) + clearNotesInFrameList(endNF); + i = -1; + itemsCount = Items->count(); + docWasChanged = true; + flag_restartMarksRenumbering = false; + continue; + } + } + if (nStyle->range() == NSRstory) + { + //restart numeration for all first frames of story chain + if (currItem->prevInChain() == NULL) + { + num = nStyle->start(); + PageItem* nextItem = currItem; + while (nextItem != NULL) + { + if (nStyle->isEndNotes() || nextItem->asTextFrame()->hasNoteFrame(nStyle, false)) + updateItemNotesNums(nextItem->asTextFrame(), nStyle, num); + nextItem = nextItem->nextInChain(); + } + } + } + else //restart numeration for each frame + { + num = nStyle->start(); + if (nStyle->isEndNotes() || currItem->asTextFrame()->hasNoteFrame(nStyle, false)) + updateItemNotesNums(currItem->asTextFrame(), nStyle, num); + } + if (currItem->asTextFrame()->hasNoteFrame(nStyle, false) && currItem->asTextFrame()->itemNoteFrame(nStyle)->invalid) + docWasChanged = true; + if (currItem->invalid) + { + currItem->layout(); + docWasChanged = true; + } + } + } + } + else if (nStyle->range() == NSRpage) + { + for (int page = 0; page < Pages->count(); ++page) + { + if (nStyle->isEndNotes() && nStyle->range() == NSRpage) + { + endNF = endNoteFrame(nStyle, (void*) DocPages.at(page)); + if (endNF != NULL) + clearNotesInFrameList(endNF); + } + //restart numeration for each page + num = nStyle->start(); + + for (i = 0; i < itemsCount; ++i) + { + PageItem* currItem = Items->at(i); + if (currItem == NULL) + continue; + if ((currItem->OwnPage == page) && currItem->isTextFrame() && !currItem->isNoteFrame() && (currItem->itemText.length() > 0)) + { + if (!currItem->asTextFrame()->isValidChainFromBegin()) + { + currItem->layout(); + if (flag_restartMarksRenumbering) + { + //restart whole update as items was changed + if (endNF != NULL) + clearNotesInFrameList(endNF); + page = -1; + i = -1; + itemsCount = Items->count(); + num = nStyle->start(); + docWasChanged = true; + flag_restartMarksRenumbering = false; + break; + } + } + if (nStyle->isEndNotes() || currItem->asTextFrame()->hasNoteFrame(nStyle, false)) + updateItemNotesNums(currItem->asTextFrame(), nStyle, num); + if (currItem->asTextFrame()->hasNoteFrame(nStyle, false) && currItem->asTextFrame()->itemNoteFrame(nStyle)->invalid) + docWasChanged = true; + if (currItem->invalid) + { + currItem->layout(); + docWasChanged = true; + } + } + } + if ((i != -1) && (num == nStyle->start()) && nStyle->isEndNotes()) + { + PageItem_NoteFrame* nF = endNoteFrame(nStyle); + if (nF != NULL && nF->isAutoNoteFrame()) + nF->deleteIt = true; + } + } + } + flag_layoutNotesFrames = true; + return docWasChanged; +} + +bool ScribusDoc::updateEndNotesNums() +{ + bool docWasChange = false; + foreach (NotesStyle* ns, m_docNotesStylesList) + { + if (ns->isEndNotes()) + { + if (updateNotesNums(ns)) + docWasChange = true; + } + } + return docWasChange; +} + +void ScribusDoc::updateNotesFramesStyles(NotesStyle *nStyle) +{ + for (int i=0; i<Items->count(); ++i) + { + PageItem* item = Items->at(i); + if (item->isNoteFrame() && (item->asNoteFrame()->notesStyle() == nStyle) && !item->asNoteFrame()->deleteIt) + { + ParagraphStyle newStyle; + if (nStyle->notesParStyle().isEmpty() || (nStyle->notesParStyle() == tr("No Style"))) + { + if (nStyle->isEndNotes()) + //set default doc style + newStyle.setParent(paragraphStyles()[0].name()); + else + { + if (item->asNoteFrame()->masterFrame() != NULL) + { + //set back style from master frame + newStyle.setParent(item->asNoteFrame()->masterFrame()->itemText.defaultStyle().parent()); + newStyle.applyStyle(item->asNoteFrame()->masterFrame()->currentStyle()); + } + else + newStyle.setParent(item->itemText.defaultStyle().parent()); + } + } + else + newStyle.setParent(nStyle->notesParStyle()); + item->itemText.setDefaultStyle(newStyle); + item->asTextFrame()->invalidateLayout(true); + } + } +} + +void ScribusDoc::updateItemNotesFramesStyles(PageItem* item, ParagraphStyle newStyle) +{ + if (item->isTextFrame() && !item->isNoteFrame()) + { + item = item->firstInChain(); + + while (item != NULL) + { + foreach (PageItem_NoteFrame* nF, item->asTextFrame()->notesFramesList()) + { + NotesStyle* nSet = nF->notesStyle(); + if (nSet->isEndNotes()) + continue; + if (nSet->notesParStyle().isEmpty() || (nSet->notesParStyle() == tr("No Style"))) + { + nF->itemText.setDefaultStyle(newStyle); + //nF->itemText.applyCharStyle(0, nF->itemText.length(), newStyle.charStyle()); + } + setNotesChanged(true); + } + item = item->nextInChain(); + } + } +} + +QList<PageItem_NoteFrame *> ScribusDoc::listNotesFrames(NotesStyle *NS) +{ + QList<PageItem_NoteFrame *> list; + foreach(PageItem* item, DocItems) + { + if (item->isNoteFrame() && item->asNoteFrame()->notesStyle() == NS) + list.append(item->asNoteFrame()); + } + return list; +} + +const ScPage *ScribusDoc::page4EndNotes(NotesStyle *NS, PageItem* item) +{ + ScPage* scP = NULL; + if ((NS->range() == NSRdocument) || ((NS->range() == NSRsection) && docPrefsData.docSectionMap.isEmpty())) + scP = DocPages.last(); + else if (item != NULL) + { + if (NS->range() == NSRpage) + scP = DocPages.at(item->OwnPage); + else if (NS->range() == NSRsection) + { + int section = getSectionKeyForPageIndex(item->OwnPage); + DocumentSection sec = sections().find(section).value(); + scP = DocPages.at(sec.toindex); + } + else if (NS->range() == NSRstory) + scP = DocPages.at(item->lastInChain()->OwnPage); + } + + return scP; +} + +bool ScribusDoc::notesFramesUpdate() +{ + bool removeEmptyNF = false; + bool docWasChanged = false; + int end = 0; + do { + setNotesChanged(false); + end = Items->count(); + for (int i = 0; i < end; ++i) + { + PageItem* item = Items->at(i); + if (!item->isTextFrame()) + continue; + if (item->isNoteFrame()) + { + if (item->asNoteFrame()->notesList().isEmpty()) + { + if (item->isAutoNoteFrame()) + item->asNoteFrame()->deleteIt = true; + } + else + { + if (item->asNoteFrame()->isEndNotesFrame()) + updateEndNotesFrameContent(item->asNoteFrame()); + else + { + if (item->itemText.length() == 0 && !item->asNoteFrame()->notesList().isEmpty()) + item->asNoteFrame()->updateNotes(item->asNoteFrame()->notesList(), true); + item->invalid = true; + item->layout(); + } + } + if (item->asNoteFrame()->deleteIt) + removeEmptyNF = true; + } + if (end != Items->count()) + { + end = Items->count(); + setNotesChanged(true); + } + docWasChanged = docWasChanged || notesChanged(); + if (notesChanged()) + break; + } + } while (notesChanged()); + + if (removeEmptyNF) + { + end = Items->count(); + QList<PageItem*> tmplist; + for (int i = 0; i < end; ++i) + { + PageItem* item = Items->at(i); + if (item->isAutoNoteFrame() && item->asNoteFrame()->deleteIt) + tmplist.append(item); + } + foreach (PageItem* item, tmplist) + { + if (item->asNoteFrame()->masterFrame()) + item->asNoteFrame()->masterFrame()->invalid = true; + delNoteFrame(item->asNoteFrame()); + } + docWasChanged = true; + } + return docWasChanged; +} + +void ScribusDoc::updateNotesFramesSettings(NotesStyle *NS) +{ + foreach (PageItem_NoteFrame* nF, listNotesFrames(NS)) + { + if (nF->isWelded() && !NS->isAutoWeldNotesFrames()) + nF->unWeld(); + if (!nF->isWelded() && NS->isAutoWeldNotesFrames()) + { + nF->setYPos(nF->masterFrame()->yPos() + nF->masterFrame()->height()); + nF->setXPos(nF->masterFrame()->xPos()); + nF->addWelded(nF->masterFrame()); + nF->masterFrame()->addWelded(nF); + nF->masterFrame()->setWeldPoint(0, nF->masterFrame()->height(), nF); + nF->setWeldPoint(0,0, nF->masterFrame()); + nF->invalidateLayout(); + } + nF->setSizeVLocked(NS->isAutoNotesHeight()); + nF->setSizeHLocked(NS->isAutoNotesWidth()); + nF->setSizeLocked(NS->isAutoNotesHeight() && NS->isAutoNotesWidth()); + if (NS->isAutoNotesHeight() || NS->isAutoNotesWidth()) + nF->invalidateLayout(); + } +} + +void ScribusDoc::updateEndnotesFrames(NotesStyle* nStyle, bool invalidate) +{ + if (m_docEndNotesFramesMap.isEmpty()) + return; + if (nStyle == NULL) + { + int NScount = m_docNotesStylesList.count(); + for (int i=0; i < NScount; ++i) + updateEndnotesFrames(m_docNotesStylesList.at(i)); + } + else if (nStyle->isEndNotes()) + { + foreach (PageItem_NoteFrame* nF, listNotesFrames(nStyle)) + updateEndNotesFrameContent(nF); + } + flag_updateEndNotes = false; +} + +//for sorting purpose +bool ascendingSort(TextNote* nt1, TextNote* nt2) { return nt1->num() < nt2->num(); } + +void ScribusDoc::updateEndNotesFrameContent(PageItem_NoteFrame *nF, bool invalidate) +{ + QList<TextNote*> nList; + foreach (PageItem* item, DocItems) + { + if (item->isTextFrame() && !item->isNoteFrame()) + { + QList<TextNote*> nL = item->asTextFrame()->notesList(nF); + if (!nL.isEmpty()) + nList.append(nL); + if (invalidate) + item->invalid = true; + } + } + + if (nList.isEmpty()) + { + if (nF->isAutoNoteFrame()) + { + nF->deleteIt = true; + m_docNotesInFrameMap.remove(nF); + delNoteFrame(nF); + } + } + else + { + NotesStyle* currNS = nF->notesStyle(); + if (currNS->isAutoNotesHeight() || currNS->isAutoNotesWidth()) + nF->invalidateLayout(); + qSort(nList.begin(), nList.end(), ascendingSort); + if (nList == m_docNotesInFrameMap.value(nF)) + return; + + nF->updateNotes(nList); + nF->invalid = true; + nF->layout(); + //layout all endnotes frames with same range + foreach (NotesStyle* NS, m_docNotesStylesList) + { + if ((NS != currNS) && (NS->isEndNotes() && NS->range() == currNS->range())) + foreach (PageItem_NoteFrame* NF, listNotesFrames(NS)) + NF->layout(); + } + m_docNotesInFrameMap.insert(nF, nList); + } +} + +void ScribusDoc::updateChangedEndNotesFrames() +{ + while (!m_docEndNotesFramesChanged.isEmpty()) + { + PageItem_NoteFrame* nF = m_docEndNotesFramesChanged.first(); + m_docEndNotesFramesChanged.removeAll(nF); + updateEndNotesFrameContent(nF); + if (nF->deleteIt && nF->isAutoNoteFrame()) + delNoteFrame(nF); + } +} + +PageItem_NoteFrame *ScribusDoc::createNoteFrame(PageItem_TextFrame *inFrame, NotesStyle *nStyle, int index) +{ + PageItem_NoteFrame* nF = new PageItem_NoteFrame(inFrame, nStyle); + if (nStyle->isEndNotes()) + m_docEndNotesFramesMap.insert(nF, rangeItem()); + m_docNotesInFrameMap.insert(nF, QList<TextNote*>()); + if (index > -1) + DocItems.insert(index, nF); + else + DocItems.append(nF); + return nF; +} + +PageItem_NoteFrame *ScribusDoc::createNoteFrame(NotesStyle *nStyle, double x, double y, double w, double h, double w2, QString fill, QString outline) +{ + PageItem_NoteFrame* nF = new PageItem_NoteFrame(nStyle, this, x, y, w, h, w2, fill, outline); + if (nStyle->isEndNotes()) + m_docEndNotesFramesMap.insert(nF, rangeItem()); + m_docNotesInFrameMap.insert(nF, QList<TextNote*>()); + DocItems.append(nF); + return nF; +} + +void ScribusDoc::delNoteFrame(PageItem_NoteFrame* nF, bool removeMarks, bool forceDeletion) +{ + Q_ASSERT(nF != NULL); + //check if note frame is listed in text frames m_notesFramesMap + if (nF->itemText.length() > 0 && removeMarks) + nF->removeMarksFromText(false); + + if (appMode == modeEdit && nF->isSelected()) + { + view()->Deselect(true); + if (!nF->isEndNotesFrame()) + view()->SelectItem(nF->masterFrame()); + } + if (m_docEndNotesFramesMap.contains(nF)) + { + m_docEndNotesFramesMap.remove(nF); + m_docEndNotesFramesChanged.removeAll(nF); + foreach (TextNote* note, nF->notesList()) + { + note->masterMark()->getItemPtr()->asTextFrame()->removeNoteFrame(nF); + note->masterMark()->getItemPtr()->invalid = true; + } + } + else if (nF->masterFrame() != NULL) + { + nF->masterFrame()->removeNoteFrame(nF); + nF->masterFrame()->invalid = true; + } + m_docNotesInFrameMap.remove(nF); + + nF->dropLinks(); + if (nF->isWelded()) + nF->unWeld(!nF->isAutoNoteFrame()); + //delete marks pointed to that item + for (int a=0; a < m_docMarksList.count(); ++a) + { + Mark* m = m_docMarksList.at(a); + Q_ASSERT(m != NULL); + if (m->isType(MARK2ItemType) && (m->getItemPtr() == nF)) + { + setUndoDelMark(m); + eraseMark(m,true); + } + } + m_Selection->delaySignalsOn(); + if (m_Selection->findItem(nF)!=-1) + { + if (appMode == modeEdit) + view()->requestMode(modeNormal); + m_Selection->removeItem(nF); + if (m_Selection->isEmpty() && nF->masterFrame()) + m_Selection->addItem(nF->masterFrame()); + } + m_Selection->delaySignalsOff(); + + Items->removeOne(nF); + setNotesChanged(true); + if (forceDeletion) + delete nF; +} + +bool ScribusDoc::validateNSet(NotesStyle NS, QString newName) +{ + //check if choosen numbering type is avaiable with choosen range, prefix and suffix + QString errStr = QString(); + foreach (NotesStyle* NS2, m_docNotesStylesList) + { + if (newName.isEmpty()) + //hack for validate nset while its name will change + newName = NS.name(); + if (newName == NS2->name()) + continue; + if (NS.range() == NS2->range()) + { + if ((NS.getType() == NS2->getType()) && (NS.prefix() == NS2->prefix()) && (NS.suffix() == NS2->suffix())) + errStr.append(NS.name() + tr("Notes style has document as range and provide same numbering style as set ") + NS2->name() + "\n"); + } + } + + if (!errStr.isEmpty() && ScCore->usingGUI()) + { + ScMessageBox::warning(this->scMW(), QObject::tr("Unaceptable settings for Notes Style"), "<qt>"+ errStr +"</qt>", QMessageBox::Ok, QMessageBox::Abort | QMessageBox::Default); + return false; + } + return true; +} + +void ScribusDoc::invalidateNoteFrames(NotesStyle *nStyle) +{ + foreach (PageItem_NoteFrame* nF, listNotesFrames(nStyle)) + nF->invalid = true; +} + +void ScribusDoc::invalidateMasterFrames(NotesStyle *nStyle) +{ + QList<PageItem*> toInvalidate; + foreach (TextNote* note, m_docNotesList) + { + if (note->notesStyle() == nStyle) + toInvalidate.append(note->masterMark()->getItemPtr()); + } + while (!toInvalidate.isEmpty()) + toInvalidate.takeFirst()->invalid = true; +} + +PageItem_NoteFrame *ScribusDoc::endNoteFrame(NotesStyle *nStyle, PageItem_TextFrame *master) +{ + if (nStyle->range() == NSRdocument) + return endNoteFrame(nStyle); + else if (nStyle->range() == NSRsection) + return endNoteFrame(nStyle, getSectionKeyForPageIndex(master->OwnPage)); + else if (nStyle->range() == NSRpage) + return endNoteFrame(nStyle, (void*) DocPages.at(master->OwnPage)); + else if (nStyle->range() == NSRstory) + return endNoteFrame(nStyle, master->firstInChain()); + return NULL; +} + +PageItem_NoteFrame* ScribusDoc::endNoteFrame(NotesStyle *nStyle, int sectIndex) +{ + if (nStyle->range() != NSRsection) + return NULL; + if (m_docEndNotesFramesMap.isEmpty()) + return NULL; + + QMap<PageItem_NoteFrame*, rangeItem>::Iterator it = m_docEndNotesFramesMap.begin(); + QMap<PageItem_NoteFrame*, rangeItem>::Iterator end = m_docEndNotesFramesMap.end(); + while (it != end) + { + PageItem_NoteFrame* nF = it.key(); + if (nF->notesStyle() == nStyle) + { + rangeItem rItem = it.value(); + if (rItem.sectionIndex == sectIndex) + return nF; + } + ++it; + } + return NULL; +} + +PageItem_NoteFrame* ScribusDoc::endNoteFrame(NotesStyle *nStyle, void* item) +{ + if (m_docEndNotesFramesMap.isEmpty()) + return NULL; + if ((nStyle->range() != NSRdocument) && (item == NULL)) + return NULL; + + QMap<PageItem_NoteFrame*, rangeItem>::Iterator it = m_docEndNotesFramesMap.begin(); + QMap<PageItem_NoteFrame*, rangeItem>::Iterator end = m_docEndNotesFramesMap.end(); + + while (it != end) + { + PageItem_NoteFrame* nF = it.key(); + rangeItem rItem = it.value(); + + if (nF->notesStyle() == nStyle) + { + if ((nStyle->range() == NSRdocument) || (item == rItem.P)) + return nF; + } + ++it; + } + return NULL; +} diff --git Scribus/scribus/scribusdoc.h Scribus/scribus/scribusdoc.h index 34a3844..99edbe1 100644 --- Scribus/scribus/scribusdoc.h +++ Scribus/scribus/scribusdoc.h @@ -41,10 +41,13 @@ for which a new license (GPL+exception) is in place. #include "scribusapi.h" #include "colormgmt/sccolormgmtengine.h" #include "documentinformation.h" +#include "marks.h" +#include "notesstyles.h" #include "observable.h" #include "pageitem.h" #include "pageitem_group.h" #include "pageitem_latexframe.h" +#include "pageitem_textframe.h" #include "pagestructs.h" #include "prefsstructs.h" #include "scguardedptr.h" @@ -75,8 +78,10 @@ class PageSize; class ScPattern; class UndoTransaction; class Serializer; - class QProgressBar; +class MarksManager; +class NotesStyle; +class TextNote; struct SCRIBUS_API NodeEditContext : public MassObservable<QPointF> { @@ -783,8 +788,9 @@ public: \param w ? \param fill fill color name \param outline outline color name + \param noteFrame optional (default false) indicates that noteframes should be created, not text frame */ - int itemAdd(const PageItem::ItemType itemType, const PageItem::ItemFrameType frameType, const double x, const double y, const double b, const double h, const double w, const QString& fill, const QString& outline, const bool itemFinalised); + int itemAdd(const PageItem::ItemType itemType, const PageItem::ItemFrameType frameType, const double x, const double y, const double b, const double h, const double w, const QString& fill, const QString& outline, const bool itemFinalised, const bool noteFrame = false); /** Add an item to the page based on the x/y position. Item will be fitted to the closest guides/margins */ int itemAddArea(const PageItem::ItemType itemType, const PageItem::ItemFrameType frameType, const double x, const double y, const double w, const QString& fill, const QString& outline, const bool itemFinalised); @@ -977,6 +983,11 @@ public: * */ void setFirstSectionFromFirstPageNumber(); + /** + * @param pageIndex page nr + * @brief Returns name of section where page is located + */ + QString getSectionNameForPageIndex(const uint pageIndex) const; //! @brief Some internal align tools typedef enum {alignFirst, alignLast, alignPage, alignMargins, alignGuide, alignSelection } AlignTo; @@ -1614,6 +1625,136 @@ public slots: void updatePict(QString name); void updatePictDir(QString name); void removePict(QString name); + +// Marks and notes +public: + /** + * Explanation + * master frame - text frame with marks for notes + * notesframe - frame with notes + * master & note mark - master is mark in "master" text, note mark is at begining of note in noteframe + */ + + //return page where endnotesframe should be located depending of notes style range and location of master mark + const ScPage* page4EndNotes(NotesStyle* NS, PageItem* item); + + //data handling structures +private: + QList<Mark*> m_docMarksList; + QList<TextNote*> m_docNotesList; + //flags used for indicating needs of updates + bool flag_notesChanged; + +public: + const QList<Mark*> marksList() { return m_docMarksList; } + const QList<TextNote*> notesList() { return m_docNotesList; } + QList<NotesStyle*> m_docNotesStylesList; + QMap<PageItem_NoteFrame*, rangeItem> m_docEndNotesFramesMap; + QList<NotesStyle*> ns2Update; //list of notes styles to update + + //returns list of notesframes for given Notes Style + QList<PageItem_NoteFrame*> listNotesFrames(NotesStyle* NS); + + //flags used for indicating needs of updates + bool notesChanged() { return flag_notesChanged; } + void setNotesChanged(bool on) { flag_notesChanged = on; } + bool flag_restartMarksRenumbering; + bool flag_updateMarksLabels; + bool flag_updateEndNotes; + bool flag_layoutNotesFrames; + + //returns list of marks labels for given mark type + QStringList marksLabelsList(MarkType type); + + //return mark definied with gioven label and given type + Mark* getMarkDefinied(QString label, MarkType type); //returns mark with label and type (labels are unique only for same type marks) + Mark* newMark(Mark* mrk = NULL); + TextNote* newNote(NotesStyle* NS); + + bool isMarkUsed(Mark* mrk, bool visible = false); + //set cursor in text where given mark will be found + void setCursor2MarkPos(Mark* mark); + //return false if mark was not found + bool eraseMark(Mark* mrk, bool fromText=false, PageItem* item=NULL, bool force = false); //force is used only for deleting non-unique marks by MarksManager + void setUndoDelMark(Mark* mrk); + //invalidate all text frames where given mark will found + //usefull spacially for varaible text marks after changing its text definition + //if forceUpdate then found master frames are relayouted + bool invalidateVariableTextFrames(Mark* mrk, bool forceUpdate = false); //returns if any text was changed + + //for foot/endnotes + NotesStyle* newNotesStyle(NotesStyle NS); + void renameNotesStyle(NotesStyle* NS, QString newName); + //delete whole notes style with its notesframes and notes + void deleteNotesStyle(QString nsName); + void undoSetNotesStyle(SimpleState* ss, NotesStyle* ns); + NotesStyle* getNotesStyle(QString nsName); + //delete note, if fromText than marks for given note will be removed + void deleteNote(TextNote* note); + void setUndoDelNote(TextNote* note); + PageItem_NoteFrame* createNoteFrame(PageItem_TextFrame* inFrame, NotesStyle *nStyle, int index = -1); + PageItem_NoteFrame* createNoteFrame(NotesStyle *nStyle, double x, double y, double w, double h, double w2, QString fill, QString outline); + //delete noteframe + void delNoteFrame(PageItem_NoteFrame *nF, bool removeMarks=true, bool forceDeletion = true); + //renumber notes for given notes style + //return true if doc needs update after changing numbers of notes + bool updateNotesNums(NotesStyle* nStyle); + //set new text styles for notes marks + void updateNotesFramesStyles(NotesStyle* nStyle); + //check conflicts beetween notes styles + bool validateNSet(NotesStyle NS, QString newName = ""); + //update layout remove empty notesframes + bool notesFramesUpdate(); + //update notesframes after changing automatic features of notes style + void updateNotesFramesSettings(NotesStyle* NS); + + //search for endnotesframe for given notes style and item holding master mark + PageItem_NoteFrame* endNoteFrame(NotesStyle* nStyle, PageItem_TextFrame* master); + // + void setEndNoteFrame(PageItem_NoteFrame* nF, void* ptr) { rangeItem rI={ptr}; m_docEndNotesFramesMap.insert(nF,rI); } + void setEndNoteFrame(PageItem_NoteFrame* nF, int section) { rangeItem rI; rI.sectionIndex = section; m_docEndNotesFramesMap.insert(nF, rI); } + //update all endnotesframes content for given notes style + void updateEndnotesFrames(NotesStyle* nStyle = NULL, bool invalidate = false); + //update endnotesframe content + void updateEndNotesFrameContent(PageItem_NoteFrame* nF, bool invalidate = false); + //insert noteframe into list of changed + void endNoteFrameChanged(PageItem_NoteFrame* nF) { m_docEndNotesFramesChanged.append(nF); } + //update content for changed endnotesframes + void updateChangedEndNotesFrames(); + //finds mark position in text + //return true if mark was found, CPos is set for mark`s position + //if item==NULL then search in all items and if mark is found than item is set + int findMarkCPos(Mark* mrk, PageItem* &item, int Start = 0); + QList<PageItem_NoteFrame*> m_docEndNotesFramesChanged; + + //finds item which holds given mark, start searching from next to lastItem index in DocItems + PageItem* findMarkItem(Mark* mrk, int &lastItem); + +private: + //QMap<PageItem_NoteFrame*, QList<TextNote *> > map of notesframes and its list of notes + NotesInFrameMap m_docNotesInFrameMap; + + PageItem* findFirstMarkItem(Mark* mrk) { int tmp = -1; return findMarkItem(mrk, tmp); } + + //search for endnotesframe for given notes style and item holding master mark or section number + PageItem_NoteFrame* endNoteFrame(NotesStyle* nStyle, void* item = NULL); + PageItem_NoteFrame* endNoteFrame(NotesStyle* nStyle, int sectIndex); + //clear list of notes for given notesframe + void clearNotesInFrameList(PageItem_NoteFrame* nF) { m_docNotesInFrameMap.insert(nF, QList<TextNote*>()); } + //renumber notes with given notes style for given frame starting from number num + void updateItemNotesNums(PageItem_TextFrame *frame, NotesStyle* nStyle, int &num); + //update notesframes text styles + void updateItemNotesFramesStyles(PageItem *item, ParagraphStyle newStyle); + + //not used? + bool updateEndNotesNums(); //return true if doc needs update + void invalidateNoteFrames(NotesStyle* nStyle); + void invalidateMasterFrames(NotesStyle* nStyle); + +public slots: + //update strings (page numbers) for marks + bool updateMarks(bool updateNotesMarks = false); + //welding two items public slots: void itemSelection_UnWeld(); diff --git Scribus/scribus/scribusstructs.h Scribus/scribus/scribusstructs.h index 20dad9e..7d65fdc 100644 --- Scribus/scribus/scribusstructs.h +++ Scribus/scribus/scribusstructs.h @@ -278,7 +278,8 @@ typedef enum { FontNotEmbedded=15, EmbeddedFontIsOpenType=16, OffConflictLayers=17, - PartFilledImageFrame= 18 + PartFilledImageFrame= 18, + MarksChanged = 19 } PreflightError; typedef QMap<PreflightError, int> errorCodes; @@ -366,6 +367,7 @@ enum UpdateRequests reqCmsOptionsUpdate = 512, reqCustomShapeUpdate = 1024, reqInlinePalUpdate = 2048, + reqMarksUpdate = 4096, reqUpdateAll = 65535 }; diff --git Scribus/scribus/scribusview.cpp Scribus/scribus/scribusview.cpp index 147500e..1ae293c 100644 --- Scribus/scribus/scribusview.cpp +++ Scribus/scribus/scribusview.cpp @@ -1718,7 +1718,7 @@ void ScribusView::HandleCurs(PageItem *currItem, QRect mpo) { if (Doc->appMode == modeRotation) qApp->changeOverrideCursor(QCursor(loadIcon("Rotieren2.png"))); - else + else if (!currItem->sizeHLocked() && ! currItem->sizeVLocked()) { double rr = fabs(currItem->rotation()); if (((rr >= 0.0) && (rr < 45.0)) || ((rr >= 135.0) && (rr < 225.0)) || @@ -2767,7 +2767,8 @@ QImage ScribusView::MPageToPixmap(QString name, int maxGr, bool drawFrame) for (int layerLevel = 0; layerLevel < layerCount; ++layerLevel) { Doc->Layers.levelToLayer(layer, layerLevel); - m_canvas->DrawPageItems(painter, layer, QRect(clipx, clipy, clipw, cliph)); + m_canvas->DrawPageItems(painter, layer, QRect(clipx, clipy, clipw, cliph), false); + m_canvas->DrawPageItems(painter, layer, QRect(clipx, clipy, clipw, cliph), true); } painter->endLayer(); painter->end(); @@ -2898,7 +2899,8 @@ QImage ScribusView::PageToPixmap(int Nr, int maxGr, bool drawFrame) { Doc->Layers.levelToLayer(layer, layerLevel); m_canvas->DrawMasterItems(painter, Doc->DocPages.at(Nr), layer, QRect(clipx, clipy, clipw, cliph)); - m_canvas->DrawPageItems(painter, layer, QRect(clipx, clipy, clipw, cliph)); + m_canvas->DrawPageItems(painter, layer, QRect(clipx, clipy, clipw, cliph), false); + m_canvas->DrawPageItems(painter, layer, QRect(clipx, clipy, clipw, cliph), true); } painter->endLayer(); painter->end(); diff --git Scribus/scribus/sctextstruct.cpp Scribus/scribus/sctextstruct.cpp index 6b20396..f3b4fa4 100644 --- Scribus/scribus/sctextstruct.cpp +++ Scribus/scribus/sctextstruct.cpp @@ -32,6 +32,7 @@ ScText::~ScText() if (parstyle) delete parstyle; parstyle = NULL; + mark = NULL; } bool ScText::hasObject(ScribusDoc *doc) const @@ -41,6 +42,18 @@ bool ScText::hasObject(ScribusDoc *doc) const return false; } +bool ScText::hasMark(Mark* MRK) const +{ + if (this->ch == SpecialChars::OBJECT) + { + if (MRK == NULL) + return mark != NULL; + else + return mark == MRK; + } + return false; +} + QList<PageItem*> ScText::getGroupedItems(ScribusDoc *doc) { QList<PageItem*> result; @@ -60,3 +73,9 @@ PageItem* ScText::getItem(ScribusDoc *doc) return doc->FrameItems[embedded]; return NULL; } + +void ScText::setNewMark(Mark *mrk) +{ + if (!mrk->isUnique()) + mark = mrk; +} diff --git Scribus/scribus/sctextstruct.h Scribus/scribus/sctextstruct.h index 7210250..0032180 100644 --- Scribus/scribus/sctextstruct.h +++ Scribus/scribus/sctextstruct.h @@ -28,6 +28,7 @@ for which a new license (GPL+exception) is in place. #include "styles/paragraphstyle.h" class PageItem; +class Mark; class ScribusDoc; /* Struktur fuer Pageitem Text */ @@ -110,16 +111,17 @@ public: float PRot; float PDx; int embedded; + Mark* mark; QChar ch; ScText() : CharStyle(), parstyle(NULL), glyph(), - PtransX(0.0f), PtransY(0.0f), PRot(0.0f), PDx(0.0f), embedded(0), ch() {} + PtransX(0.0f), PtransY(0.0f), PRot(0.0f), PDx(0.0f), embedded(0), mark(NULL), ch() {} ScText(const ScText& other) : CharStyle(other), parstyle(NULL), glyph(other.glyph), PtransX(other.PtransX), PtransY(other.PtransY), PRot(other.PRot), PDx(other.PDx), - embedded(other.embedded), ch(other.ch) + embedded(other.embedded), mark(NULL), ch(other.ch) { glyph.more = NULL; GlyphLayout *layout = &glyph; @@ -132,12 +134,18 @@ public: } if (other.parstyle) parstyle = new ParagraphStyle(*other.parstyle); + if (other.mark) + setNewMark(other.mark); } ~ScText(); bool hasObject(ScribusDoc *doc) const; + //returns true if given MRK is found, if MRK is NULL then any mark returns true + bool hasMark(Mark * MRK = NULL) const; QList<PageItem*> getGroupedItems(ScribusDoc *doc); PageItem* getItem(ScribusDoc *doc); +private: + void setNewMark(Mark* mrk); }; #endif diff --git Scribus/scribus/serializer.h Scribus/scribus/serializer.h index 2e7a498..f6382cc 100644 --- Scribus/scribus/serializer.h +++ Scribus/scribus/serializer.h @@ -53,7 +53,7 @@ public: elements. Since it has Digester as a superclass, a Serializer object can also be used where a SaxHandler is required as argument, eg. the saxx() method. */ - Serializer(ScribusDoc& doc); + Serializer(ScribusDoc& doc); //saxing notes needs doc /** Writes all objects in selection to handler as a fragment. Needed styles and colors are included. diff --git Scribus/scribus/text/storytext.cpp Scribus/scribus/text/storytext.cpp index c760855..7bc4083 100644 --- Scribus/scribus/text/storytext.cpp +++ Scribus/scribus/text/storytext.cpp @@ -26,9 +26,11 @@ pageitem.cpp - description #include <QList> #include <cassert> //added to make Fedora-5 happy #include "fpoint.h" +#include "notesstyles.h" #include "scfonts.h" #include "scribusdoc.h" #include "sctext_shared.h" +#include "selection.h" #include "storytext.h" #include "scribus.h" #include "util.h" @@ -327,6 +329,7 @@ void StoryText::insert(int pos, const StoryText& other, bool onlySelection) else if (other.text(i) == SpecialChars::OBJECT) { insertChars(pos, SpecialChars::OBJECT); item(pos)->embedded = other.item(i)->embedded; + item(pos)->mark = other.item(i)->mark; applyCharStyle(pos, 1, other.charStyle(i)); cstyleStart = i+1; pos += 1; @@ -632,6 +635,17 @@ void StoryText::insertObject(int pos, int ob) doc->FrameItems[ob]->OwnPage = -1; // #10379: OwnPage is not meaningful for inline object } +void StoryText::insertMark(Mark* Mark, int pos) +{ + if (Mark == NULL) + return; + if (pos < 0) + pos = d->cursorPosition; + + insertChars(pos, SpecialChars::OBJECT, false); + const_cast<StoryText *>(this)->d->at(pos)->mark = Mark; +} + void StoryText::replaceObject(int pos, int ob) { if (pos < 0) @@ -657,7 +671,7 @@ QString StoryText::plainText() const QChar ch; QString result; - uint len = length(); + int len = length(); result.reserve(len); StoryText* that(const_cast<StoryText*>(this)); @@ -761,6 +775,32 @@ PageItem* StoryText::object(int pos) const return that->d->at(pos)->getItem(doc); } +bool StoryText::hasMark(int pos) const +{ + if (pos < 0) + pos += length(); + + assert(pos >= 0); + assert(pos < length()); + + StoryText* that = const_cast<StoryText *>(this); + if (that->d->at(pos)->ch == SpecialChars::OBJECT) + return that->d->at(pos)->hasMark(); + return false; +} + +Mark* StoryText::mark(int pos) const +{ + if (pos < 0) + pos += length(); + + assert(pos >= 0); + assert(pos < length()); + + StoryText* that = const_cast<StoryText *>(this); + return that->d->at(pos)->mark; +} + const CharStyle & StoryText::charStyle() const { return charStyle(d->cursorPosition); @@ -782,9 +822,11 @@ const CharStyle & StoryText::charStyle(int pos) const qDebug() << "storytext::charstyle: access at end of text %i" << pos; --pos; } + //for notes frames - get style from note text, not from mark + if ((pos+1 < length()) && hasMark(pos) && mark(pos)->isNoteType()) + ++pos; if (text(pos) == SpecialChars::PARSEP) return paragraphStyle(pos).charStyle(); - StoryText* that = const_cast<StoryText *>(this); return dynamic_cast<const CharStyle &> (*that->d->at(pos)); } @@ -1464,7 +1506,13 @@ int StoryText::endOfSelection() const int StoryText::lengthOfSelection() const { - return selFirst <= selLast? selLast - selFirst + 1 : 0; + //FIX ME - sometimes I saw values equal or greater than length of text + int last = selLast; + if (selFirst >= length()) + return 0; + if (selLast >= length()) + last = length() -1; + return selFirst <= last? last - selFirst + 1 : 0; } @@ -1634,6 +1682,8 @@ void StoryText::invalidate(int firstItem, int endItem) if (par) par->charStyleContext()->invalidate(); } + if (!signalsBlocked()) + emit changed(); emit changed(); } @@ -1868,6 +1918,38 @@ void StoryText::saxx(SaxHandler& handler, const Xml_string& elemtag) const { object(i)->saxx(handler); } + else if (hasMark(i)) + { + Mark* mrk = mark(i); + if ((doc->m_Selection->itemAt(0)->isNoteFrame() && mrk->isType(MARKNoteMasterType)) + || (!doc->m_Selection->itemAt(0)->isTextFrame() && mrk->isType(MARKNoteFrameType))) + continue; //do not insert notes marks into text frames nad vice versa + Xml_attr mark_attr; + mark_attr.insert("label", mrk->label); + mark_attr.insert("typ", QString::number((int )mrk->getType())); + if (mrk->isType(MARK2ItemType) && (mrk->getItemPtr() != NULL)) + mark_attr.insert("item", mrk->getItemPtr()->itemName()); + else if (mrk->isType(MARK2MarkType)) + { + QString l; + MarkType t; + mrk->getMark(l, t); + if (doc->getMarkDefinied(l,t) != NULL) + { + mark_attr.insert("mark_l", l); + mark_attr.insert("mark_t", QString::number((int) t)); + } + } + else if (mrk->isType(MARKNoteMasterType)) + { + mark_attr.insert("nStyle", mrk->getNotePtr()->notesStyle()->name()); + mark_attr.insert("note",mrk->getNotePtr()->saxedText()); + //store noteframe name for inserting into note if it is non-auto-removable + if (!mrk->getNotePtr()->noteMark()->getItemPtr()->isAutoNoteFrame()) + mark_attr.insert("noteframe", mrk->getNotePtr()->noteMark()->getItemPtr()->getUName()); + } + handler.beginEnd("mark", mark_attr); + } else if (curr == SpecialChars::TAB) { handler.beginEnd("tab", empty); @@ -2028,6 +2110,92 @@ public: struct AppendInlineFrame : public MakeAction<AppendInlineFrame_body> {}; +//marks support +class AppendMark_body : public Action_body +{ +public: + void begin(const Xml_string& tag, Xml_attr attr) + { + StoryText* story = this->dig->top<StoryText>(); + QString l = ""; + MarkType t = MARKNoType; + + Mark* mrk = NULL; + + if (tag == "mark") + { + Xml_attr::iterator lIt = attr.find("label"); + Xml_attr::iterator tIt = attr.find("typ"); + Xml_attr::iterator iIt = attr.find("item"); + Xml_attr::iterator m_lIt = attr.find("mark_l"); + Xml_attr::iterator m_tIt = attr.find("mark_t"); + Xml_attr::iterator nf_It = attr.find("noteframe"); + if (lIt != attr.end()) + l = Xml_data(lIt); + if (tIt != attr.end()) + t = (MarkType) parseInt(Xml_data(tIt)); + ScribusDoc* doc = this->dig->lookup<ScribusDoc>("<scribusdoc>"); + if (t == MARKVariableTextType) + mrk = doc->getMarkDefinied(l,t); + else + { + mrk = doc->newMark(); + getUniqueName(l,doc->marksLabelsList(t), "_"); + mrk->label = l; + mrk->OwnPage = doc->currentPage()->pageNr(); + mrk->setType(t); + if (mrk->isType(MARK2ItemType) && (iIt != attr.end())) + { + PageItem* item = doc->getItemFromName(Xml_data(iIt)); + mrk->setItemPtr(item); + if (item == NULL) + mrk->setString("0"); + else + mrk->setString(QString::number(item->OwnPage)); + mrk->setItemName(Xml_data(iIt)); + } + if (mrk->isType(MARK2MarkType) && (m_lIt != attr.end()) && (m_tIt != attr.end())) + { + Mark* targetMark = doc->getMarkDefinied(Xml_data(m_lIt), (MarkType) parseInt(Xml_data(m_tIt))); + mrk->setMark(targetMark); + if (targetMark == NULL) + mrk->setString("0"); + else + mrk->setString(QString::number(targetMark->OwnPage)); + mrk->setItemName(Xml_data(m_lIt)); + } + if (mrk->isType(MARKNoteMasterType)) + { + Xml_attr::iterator nIt = attr.find("note"); + Xml_attr::iterator nsIt = attr.find("nStyle"); + NotesStyle* NS; + if (nsIt == attr.end()) + NS = doc->m_docNotesStylesList.at(0); + else + NS = doc->getNotesStyle(Xml_data(nsIt)); + TextNote* note = doc->newNote(NS); + note->setMasterMark(mrk); + if (nIt != attr.end()) + note->setSaxedText(Xml_data(nIt)); +// if (!NS->isAutoRemoveEmptyNotesFrames() && (nf_It != attr.end())) +// { +// PageItem_NoteFrame* nF = (PageItem_NoteFrame*) doc->getItemFromName(Xml_data(nf_It)); +// if (nF != NULL) +// doc->m_Selection->itemAt(0)->asTextFrame()->setNoteFrame(nF); +// } + mrk->setNotePtr(note); + doc->setNotesChanged(true); + } + doc->newMark(mrk); + } + story->insertMark(mrk); + } + } +}; + +struct AppendMark : public MakeAction<AppendMark_body> +{}; + /* class ApplyStyle_body : public Action_body { @@ -2252,5 +2420,6 @@ void StoryText::desaxeRules(const Xml_string& prefixPattern, Digester& ruleset, //PageItem::desaxeRules(storyPrefix, ruleset); argh, that would be recursive! ruleset.addRule(Digester::concat(spanPrefix, "item"), AppendInlineFrame() ); + ruleset.addRule(Digester::concat(spanPrefix, "mark"), AppendMark() ); } diff --git Scribus/scribus/text/storytext.h Scribus/scribus/text/storytext.h index ae281d5..e531d03 100644 --- Scribus/scribus/text/storytext.h +++ Scribus/scribus/text/storytext.h @@ -30,6 +30,7 @@ pageitem.cpp - description #include <QList> #include <cassert> +#include "marks.h" //#include "text/paragraphlayout.h" #include "text/frect.h" #include "text/specialchars.h" @@ -132,6 +133,8 @@ class SCRIBUS_API StoryText : public QObject, public SaxIO void insertObject(int obj); // Insert object at specific position void insertObject(int pos, int obj); + // Insert mark at cursor or specific position + void insertMark(Mark* Mark, int pos = -1); void replaceChar(int pos, QChar ch); // Replaced a word, and return the difference in length between old and new int replaceWord(int pos, QString newWord); @@ -161,6 +164,8 @@ class SCRIBUS_API StoryText : public QObject, public SaxIO bool hasObject(int pos) const; PageItem* object(int pos) const; + bool hasMark(int pos) const; + Mark *mark(int pos) const; int nextCharPos(int c); int prevCharPos(int c); diff --git Scribus/scribus/ui/MarkInsertDlg.h Scribus/scribus/ui/MarkInsertDlg.h new file mode 100644 index 0000000..0c228f0 --- /dev/null +++ Scribus/scribus/ui/MarkInsertDlg.h @@ -0,0 +1,40 @@ +#ifndef MARKINSERTDLG_H +#define MARKINSERTDLG_H + +#include <QDialog> +#include <scribusapi.h> + +class NotesStyle; +class Mark; +class PageItem; + +class SCRIBUS_API MarkInsertDlg : public QDialog +{ + Q_OBJECT + +public: + MarkInsertDlg(const QList<Mark*>&, QWidget *parent = 0) : QDialog(parent) {} + MarkInsertDlg(const Mark*, QWidget *parent = 0) : QDialog(parent) {} + MarkInsertDlg(const QList<NotesStyle*>&, QWidget *parent = 0) : QDialog(parent) {} + MarkInsertDlg(QWidget *parent = 0) : QDialog(parent) {} + ~MarkInsertDlg() {} + + virtual void values(QString &label) {} + virtual void values(QString &label, PageItem* &item) {} + virtual Mark* values(QString& label, QString& text) { return NULL; } + virtual void values(QString& label, Mark* &mrk) {} + virtual NotesStyle* values() { return NULL; } + + virtual void setValues(const QString label) {} + virtual void setValues(const QString label, const QString text) {} + virtual void setValues(const QString label, const PageItem* ptr) {} + virtual void setValues(const QString label, const Mark* ptr) {} + virtual void setValues(const NotesStyle* defaultStyle) {} + +signals: + +public slots: + +}; + +#endif // MARKINSERTDLG_H diff --git Scribus/scribus/ui/checkDocument.cpp Scribus/scribus/ui/checkDocument.cpp index b5a4dbf..5de6ee7 100644 --- Scribus/scribus/ui/checkDocument.cpp +++ Scribus/scribus/ui/checkDocument.cpp @@ -313,7 +313,9 @@ void CheckDocument::buildErrorList(ScribusDoc *doc) if ((doc->docItemErrors.count() == 0) && (doc->masterItemErrors.count() == 0) - && (doc->docLayerErrors.count() == 0)) + && (doc->docLayerErrors.count() == 0) + //this flag is used by documentchecker as indicator for marks change after updating + && !doc->notesChanged()) { QTreeWidgetItem * documentItem = new QTreeWidgetItem( reportDisplay ); documentItem->setText(COLUMN_ITEM, tr( "Document" ) ); @@ -329,6 +331,16 @@ void CheckDocument::buildErrorList(ScribusDoc *doc) bool layoutGraveError = false; itemError = false; // QTreeWidgetItem * pagep = 0; + + // MARKS *********************************************** + if (doc->notesChanged()) + { + QTreeWidgetItem * marksItem = new QTreeWidgetItem(reportDisplay); + marksItem->setText(0, tr("After Marks update document was changed")); + marksItem->setIcon(COLUMN_ITEM, onlyWarning ); + doc->setNotesChanged(false); + } + // LAYERS **********************************************8 QTreeWidgetItem * layerItem = new QTreeWidgetItem(reportDisplay); layerItem->setText(COLUMN_ITEM, tr("Layers")); diff --git Scribus/scribus/ui/contextmenu.cpp Scribus/scribus/ui/contextmenu.cpp index dd40a62..139c4cc 100644 --- Scribus/scribus/ui/contextmenu.cpp +++ Scribus/scribus/ui/contextmenu.cpp @@ -24,6 +24,7 @@ #include "contextmenu.h" #include "prefsmanager.h" +#include "pageitem_textframe.h" #include "scmimedata.h" #include "scraction.h" #include "scrapbookpalette.h" @@ -94,6 +95,7 @@ void ContextMenu::createMenuItems_Selection() QMenu *menuLayer = new QMenu(this); QMenu *menuLevel = new QMenu(this); QMenu *menuPDF = new QMenu(this); + QMenu *menuMark = new QMenu(this); QMenu *menuResolution = new QMenu(this); // QMenu *menuWeld = new QMenu(this); @@ -165,6 +167,34 @@ void ContextMenu::createMenuItems_Selection() addSeparator(); addAction(m_AP->scrActions["editEditRenderSource"]); } + if (m_doc->appMode == modeEdit) + { + //add actions for marks in edit mode + addSeparator(); + QAction *act2 = addMenu(menuMark); + act2->setText( ScribusView::tr("Insert Mark")); + menuMark->addAction(m_AP->scrActions["insertMarkVariableText"]); + if (m_actionList.contains("insertMarkAnchor")) + { + menuMark->addAction(m_AP->scrActions["insertMarkAnchor"]); + menuMark->addAction(m_AP->scrActions["insertMarkItem"]); + menuMark->addAction(m_AP->scrActions["insertMark2Mark"]); + if (!currItem->isNoteFrame()) + menuMark->addAction(m_AP->scrActions["insertMarkNote"]); + // menuMark->addAction(m_AP->scrActions["insertMarkIndex"]); + } + if (currItem->itemText.cursorPosition() < currItem->itemText.length()) + { + ScText *hl = currItem->itemText.item(currItem->itemText.cursorPosition()); + if (hl->hasMark()) + addAction(m_AP->scrActions["editMark"]); + } + } + if (!m_doc->marksList().isEmpty()) + { + addSeparator(); + addAction(m_AP->scrActions["itemUpdateMarks"]); + } if (m_actionList.contains("fileImportText")) { addSeparator(); diff --git Scribus/scribus/ui/loremipsum.cpp Scribus/scribus/ui/loremipsum.cpp index acdb3f7..37c71e6 100644 --- Scribus/scribus/ui/loremipsum.cpp +++ Scribus/scribus/ui/loremipsum.cpp @@ -282,6 +282,12 @@ void LoremManager::insertLoremIpsum(QString name, int paraCount, bool random) PageItem* currItem = m_Doc->m_Selection->itemAt(i); if (currItem == NULL) continue; + //do not insert lorem ipsum text into notes frames + if (currItem->isNoteFrame()) + continue; + //removing marks and notes from current text +// if (currItem->isTextFrame() && !currItem->asTextFrame()->removeMarksFromText(!m_Doc->hasGUI())) +// continue; PageItem *i2 = currItem; if (m_Doc->appMode == modeEditTable) i2 = currItem->asTable()->activeCell().textFrame(); @@ -346,7 +352,7 @@ void LoremManager::insertLoremIpsum(QString name, int paraCount, bool random) delete lp; if (m_Doc->docHyphenator->AutoCheck) m_Doc->docHyphenator->slotHyphenate(i2); - i2->invalidateLayout(); + i2->asTextFrame()->invalidateLayout(true); } m_Doc->regionsChanged()->update(QRectF()); m_Doc->changed(); diff --git Scribus/scribus/ui/mark2item.cpp Scribus/scribus/ui/mark2item.cpp new file mode 100644 index 0000000..1608b83 --- /dev/null +++ Scribus/scribus/ui/mark2item.cpp @@ -0,0 +1,51 @@ +#include "mark2item.h" +//#include "notesstyles.h" +#include "pageitem_noteframe.h" +#include "scribus.h" + +Mark2ItemDlg::Mark2ItemDlg(QWidget *parent) : MarkInsertDlg(parent) +{ + setupUi(this); + ScribusMainWindow* scmw = (ScribusMainWindow*) parent; + QStringList itemsList; + + for (int i = 0; i < scmw->doc->Items->count(); i++) + { + PageItem* item = scmw->doc->Items->at(i); + if (item->isAutoNoteFrame()) + continue; //omit notes frames automaticaly created and removed + itemsList.append(item->itemName()); + } + ItemList->addItems(itemsList); + setWindowTitle(tr("Mark to Item")); +} + +void Mark2ItemDlg::values(QString &label, PageItem* &ptr) +{ + QString itemName = ItemList->currentText(); + if (itemName != "") + { + ScribusMainWindow* scmw = (ScribusMainWindow*) parent(); + ptr = scmw->doc->getItemFromName(itemName); + label = labelEdit->text(); + } +} + +void Mark2ItemDlg::setValues(const QString label, const PageItem* ptr) +{ + int index = (ptr == NULL)? -1:ItemList->findText(ptr->itemName()); + ItemList->setCurrentIndex(index); + labelEdit->setText(label); +} + +void Mark2ItemDlg::changeEvent(QEvent *e) +{ + QDialog::changeEvent(e); + switch (e->type()) { + case QEvent::LanguageChange: + retranslateUi(this); + break; + default: + break; + } +} diff --git Scribus/scribus/ui/mark2item.h Scribus/scribus/ui/mark2item.h new file mode 100644 index 0000000..6565fef --- /dev/null +++ Scribus/scribus/ui/mark2item.h @@ -0,0 +1,20 @@ +#ifndef MARK2ITEM_H +#define MARK2ITEM_H + +#include "MarkInsertDlg.h" +#include "ui_mark2item.h" + +class SCRIBUS_API Mark2ItemDlg : public MarkInsertDlg, private Ui::Mark2ItemDlg +{ + Q_OBJECT + +public: + explicit Mark2ItemDlg(QWidget *parent = 0); + virtual void values(QString &label, PageItem* &ptr); + virtual void setValues(const QString label, const PageItem* ptr); + +protected: + void changeEvent(QEvent *e); +}; + +#endif // MARK2ITEM_H diff --git Scribus/scribus/ui/mark2item.ui Scribus/scribus/ui/mark2item.ui new file mode 100644 index 0000000..0a7aea3 --- /dev/null +++ Scribus/scribus/ui/mark2item.ui @@ -0,0 +1,142 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Mark2ItemDlg</class> + <widget class="QDialog" name="Mark2ItemDlg"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>349</width> + <height>102</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>115</height> + </size> + </property> + <property name="windowTitle"> + <string>Dialog</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <layout class="QFormLayout" name="formLayout"> + <property name="fieldGrowthPolicy"> + <enum>QFormLayout::AllNonFixedFieldsGrow</enum> + </property> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Label:</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLineEdit" name="labelEdit"/> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Item:</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QComboBox" name="ItemList"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="editable"> + <bool>false</bool> + </property> + <property name="currentIndex"> + <number>-1</number> + </property> + <property name="duplicatesEnabled"> + <bool>false</bool> + </property> + </widget> + </item> + </layout> + </item> + <item row="1" column="0"> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>164</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>Mark2ItemDlg</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>262</x> + <y>90</y> + </hint> + <hint type="destinationlabel"> + <x>174</x> + <y>54</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>Mark2ItemDlg</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>262</x> + <y>90</y> + </hint> + <hint type="destinationlabel"> + <x>174</x> + <y>54</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git Scribus/scribus/ui/mark2mark.cpp Scribus/scribus/ui/mark2mark.cpp new file mode 100644 index 0000000..6033c11 --- /dev/null +++ Scribus/scribus/ui/mark2mark.cpp @@ -0,0 +1,101 @@ +#include "marks.h" +#include "mark2mark.h" +#include <QStandardItemModel> + +Mark2MarkDlg::Mark2MarkDlg(const QList<Mark*>& marks, Mark* omitMark, QWidget *parent) : MarkInsertDlg(marks, parent) +{ + setupUi(this); + LabelList->addItem("", QVariant::fromValue((void*) NULL)); + + //for each marks type + QString typeStr; + MarkType typeMrk; + + int index = 0; + typeMrk = MARKAnchorType; typeStr = tr("Anchors"); + //adding name of marks type, and make it unselectable + LabelList->addItem("+++ " + typeStr); + qobject_cast<QStandardItemModel *>(LabelList->model())->item( ++index )->setEnabled( false ); + for (int i = 0; i < marks.size(); ++i) + { + if (marks[i]->isType(typeMrk)) + { + LabelList->addItem(marks[i]->label, QVariant::fromValue((void*) marks[i])); + index++; + } + } + typeMrk = MARK2MarkType; typeStr = tr("Mark to Mark"); + LabelList->addItem("+++ " + typeStr); + qobject_cast<QStandardItemModel *>(LabelList->model())->item( ++index )->setEnabled( false ); + for (int i = 0; i < marks.size(); ++i) + { + if (marks[i]->isType(typeMrk) && marks[i] != omitMark) + { + LabelList->addItem(marks[i]->label, QVariant::fromValue((void*) marks[i])); + index++; + } + } + typeMrk = MARK2ItemType; typeStr = tr("Mark to Item"); + LabelList->addItem("+++ " + typeStr); + qobject_cast<QStandardItemModel *>(LabelList->model())->item( ++index )->setEnabled( false ); + for (int i = 0; i < marks.size(); ++i) + { + if (marks[i]->isType(typeMrk)) + { + LabelList->addItem(marks[i]->label, QVariant::fromValue((void*) marks[i])); + index++; + } + } + typeMrk = MARKNoteMasterType; typeStr = tr("Note mark"); + LabelList->addItem("+++ " + typeStr); + qobject_cast<QStandardItemModel *>(LabelList->model())->item( ++index )->setEnabled( false ); + for (int i = 0; i < marks.size(); ++i) + { + if (marks[i]->isType(typeMrk)) + { + LabelList->addItem(marks[i]->label, QVariant::fromValue((void*) marks[i])); + index++; + } + } +// typeMrk = MARKIndexType; typeStr = tr("Index entry"); +// LabelList->addItem("+++ " + typeStr); +// qobject_cast<QStandardItemModel *>(LabelList->model())->item( ++index )->setEnabled( false ); +// for (int i = 0; i < marks.size(); ++i) +// { +// if (marks[i]->isType(typeMrk)) +// { +// LabelList->addItem(marks[i]->label, QVariant::fromValue((void*) marks[i])); +// index++; +// } +// } + setWindowTitle(tr("Mark to Mark")); +} + +void Mark2MarkDlg::values(QString& label, Mark* &mrk) +{ + label = this->labelEdit->text(); + int labelID = LabelList->currentIndex(); + if (labelID == 0) + mrk= NULL; + else + mrk = (Mark*) LabelList->itemData(labelID).value<void*>(); +} + +void Mark2MarkDlg::setValues(const QString label, const Mark* mrk) +{ + int index = (mrk == NULL)? -1:LabelList->findText(mrk->label); + LabelList->setCurrentIndex(index); + labelEdit->setText(label); +} + +void Mark2MarkDlg::changeEvent(QEvent *e) +{ + QDialog::changeEvent(e); + switch (e->type()) { + case QEvent::LanguageChange: + retranslateUi(this); + break; + default: + break; + } +} diff --git Scribus/scribus/ui/mark2mark.h Scribus/scribus/ui/mark2mark.h new file mode 100644 index 0000000..7104329 --- /dev/null +++ Scribus/scribus/ui/mark2mark.h @@ -0,0 +1,20 @@ +#ifndef MARK2MARK_H +#define MARK2MARK_H + +#include "MarkInsertDlg.h" +#include "ui_mark2mark.h" + +class SCRIBUS_API Mark2MarkDlg : public MarkInsertDlg, private Ui::Mark2MarkDlg +{ + Q_OBJECT + +public: + explicit Mark2MarkDlg(const QList<Mark*>& marks, Mark* omitMark = NULL, QWidget *parent = NULL); + virtual void values(QString& label, Mark* &mrk); + virtual void setValues(const QString label, const Mark* mrk); + +protected: + void changeEvent(QEvent *e); +}; + +#endif // MARK2MARK_H diff --git Scribus/scribus/ui/mark2mark.ui Scribus/scribus/ui/mark2mark.ui new file mode 100644 index 0000000..9b7d069 --- /dev/null +++ Scribus/scribus/ui/mark2mark.ui @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Mark2MarkDlg</class> + <widget class="QDialog" name="Mark2MarkDlg"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>362</width> + <height>103</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>103</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>103</height> + </size> + </property> + <property name="windowTitle"> + <string>Dialog</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QSplitter" name="splitter"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Label:</string> + </property> + </widget> + <widget class="QLineEdit" name="labelEdit"/> + </widget> + </item> + <item> + <widget class="QSplitter" name="splitter_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Select marker:</string> + </property> + </widget> + <widget class="QComboBox" name="LabelList"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="editable"> + <bool>false</bool> + </property> + <property name="currentIndex"> + <number>-1</number> + </property> + <property name="duplicatesEnabled"> + <bool>false</bool> + </property> + </widget> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>166</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>Mark2MarkDlg</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>262</x> + <y>90</y> + </hint> + <hint type="destinationlabel"> + <x>174</x> + <y>54</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>Mark2MarkDlg</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>262</x> + <y>90</y> + </hint> + <hint type="destinationlabel"> + <x>174</x> + <y>54</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git Scribus/scribus/ui/markanchor.cpp Scribus/scribus/ui/markanchor.cpp new file mode 100644 index 0000000..93867e7 --- /dev/null +++ Scribus/scribus/ui/markanchor.cpp @@ -0,0 +1,30 @@ +#include "markanchor.h" + +MarkAnchorDlg::MarkAnchorDlg(QWidget *parent) : + MarkInsertDlg(parent) +{ + setupUi(this); + setWindowTitle(tr("Anchor Mark")); +} + +void MarkAnchorDlg:: values(QString& label) +{ + label = labelEdit->text(); +} + +void MarkAnchorDlg::setValues(const QString label) +{ + labelEdit->setText(label); +} + +void MarkAnchorDlg::changeEvent(QEvent *e) +{ + QDialog::changeEvent(e); + switch (e->type()) { + case QEvent::LanguageChange: + retranslateUi(this); + break; + default: + break; + } +} diff --git Scribus/scribus/ui/markanchor.h Scribus/scribus/ui/markanchor.h new file mode 100644 index 0000000..cd13b5a --- /dev/null +++ Scribus/scribus/ui/markanchor.h @@ -0,0 +1,20 @@ +#ifndef MARKANCHOR_H +#define MARKANCHOR_H + +#include "MarkInsertDlg.h" +#include "ui_markanchor.h" + +class SCRIBUS_API MarkAnchorDlg : public MarkInsertDlg, private Ui::MarkAnchorDlg +{ + Q_OBJECT + +public: + explicit MarkAnchorDlg(QWidget *parent = 0); + ~MarkAnchorDlg() {} + virtual void values(QString& label); + virtual void setValues(const QString label); +protected: + void changeEvent(QEvent *e); +}; + +#endif // MARKANCHOR_H diff --git Scribus/scribus/ui/markanchor.ui Scribus/scribus/ui/markanchor.ui new file mode 100644 index 0000000..f152fcd --- /dev/null +++ Scribus/scribus/ui/markanchor.ui @@ -0,0 +1,92 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>MarkAnchorDlg</class> + <widget class="QDialog" name="MarkAnchorDlg"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>400</width> + <height>81</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>81</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>81</height> + </size> + </property> + <property name="windowTitle"> + <string>Dialog</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Label:</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLineEdit" name="labelEdit"/> + </item> + <item row="1" column="1"> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>MarkAnchorDlg</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>MarkAnchorDlg</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git Scribus/scribus/ui/marknote.cpp Scribus/scribus/ui/marknote.cpp new file mode 100644 index 0000000..1c4b467 --- /dev/null +++ Scribus/scribus/ui/marknote.cpp @@ -0,0 +1,43 @@ +#include "marknote.h" +#include "scribus.h" + +static int lastNotesStyleIndex = 0; //remember last selected notes style + +MarkNoteDlg::MarkNoteDlg(const QList<NotesStyle*>& notesStylesList, QWidget *parent) : + MarkInsertDlg(notesStylesList, parent) +{ + setupUi(this); + + for (int i = 0; i < notesStylesList.count(); i++) + ItemList->addItem(notesStylesList.at(i)->name(), QVariant::fromValue((void*) notesStylesList.at(i))); + setWindowTitle(tr("Insert Foot/Endnote")); + ItemList->setCurrentIndex(lastNotesStyleIndex); +} + +NotesStyle* MarkNoteDlg::values() +{ + int index = ItemList->currentIndex(); + return (NotesStyle*) ItemList->itemData(index).value<void*>(); +} + +void MarkNoteDlg::setValues(NotesStyle* defaultStyle) +{ + ItemList->setCurrentIndex(ItemList->findText(defaultStyle->name())); +} + +void MarkNoteDlg::changeEvent(QEvent *e) +{ + QDialog::changeEvent(e); + switch (e->type()) { + case QEvent::LanguageChange: + retranslateUi(this); + break; + default: + break; + } +} + +void MarkNoteDlg::on_buttonBox_accepted() +{ + lastNotesStyleIndex = ItemList->currentIndex(); +} diff --git Scribus/scribus/ui/marknote.h Scribus/scribus/ui/marknote.h new file mode 100644 index 0000000..c09379d --- /dev/null +++ Scribus/scribus/ui/marknote.h @@ -0,0 +1,22 @@ +#ifndef MARKNOTE_H +#define MARKNOTE_H + +#include "MarkInsertDlg.h" +#include "notesstyles.h" +#include "ui_marknote.h" + +class SCRIBUS_API MarkNoteDlg : public MarkInsertDlg, private Ui::MarkNoteDlg +{ + Q_OBJECT + +public: + explicit MarkNoteDlg(const QList<NotesStyle*>& notesStylesList, QWidget *parent = NULL); + virtual NotesStyle* values(); + virtual void setValues(NotesStyle* defaultStyle); +protected: + void changeEvent(QEvent *e); +private slots: + void on_buttonBox_accepted(); +}; + +#endif // MARKNOTE_H diff --git Scribus/scribus/ui/marknote.ui Scribus/scribus/ui/marknote.ui new file mode 100644 index 0000000..1098160 --- /dev/null +++ Scribus/scribus/ui/marknote.ui @@ -0,0 +1,115 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>MarkNoteDlg</class> + <widget class="QDialog" name="MarkNoteDlg"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>358</width> + <height>80</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>80</height> + </size> + </property> + <property name="windowTitle"> + <string>Dialog</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <layout class="QFormLayout" name="formLayout"> + <property name="fieldGrowthPolicy"> + <enum>QFormLayout::AllNonFixedFieldsGrow</enum> + </property> + <property name="formAlignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> + </property> + <item row="0" column="1"> + <widget class="QComboBox" name="ItemList"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="editable"> + <bool>false</bool> + </property> + <property name="currentIndex"> + <number>-1</number> + </property> + <property name="duplicatesEnabled"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="0" column="0"> + <widget class="QLabel" name="label_2"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Notes Style:</string> + </property> + </widget> + </item> + </layout> + </item> + <item row="1" column="0"> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>MarkNoteDlg</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>178</x> + <y>55</y> + </hint> + <hint type="destinationlabel"> + <x>178</x> + <y>39</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>MarkNoteDlg</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>178</x> + <y>55</y> + </hint> + <hint type="destinationlabel"> + <x>178</x> + <y>39</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git Scribus/scribus/ui/marksmanager.cpp Scribus/scribus/ui/marksmanager.cpp new file mode 100644 index 0000000..1455291 --- /dev/null +++ Scribus/scribus/ui/marksmanager.cpp @@ -0,0 +1,238 @@ +#include "marksmanager.h" +#include "notesstyles.h" +#include "prefsmanager.h" +#include "prefsfile.h" +#include "scribus.h" +#include "scribusdoc.h" +#include "undomanager.h" +#include <QStandardItemModel> + +MarksManager::MarksManager(QWidget *parent, const char *name) + : ScrPaletteBase(parent, name), m_Doc(NULL) +{ + setupUi(this); + listView->setSelectionMode(QAbstractItemView::SingleSelection); + listView->setSortingEnabled(true); + listView->setHeaderHidden(true); + listView->setColumnCount(1); + QString pname(name); + if (pname.isEmpty()) + pname = "marksManager"; + m_prefs = PrefsManager::instance()->prefsFile->getContext(pname); + setDoc(0); + languageChange(); + EditButton->setEnabled(false); + DeleteButton->setEnabled(false); + UpdateButton->setEnabled(false); +} + +MarksManager::~MarksManager() +{ + storeVisibility(this->isVisible()); + storePosition(); + storeSize(); +} + +void MarksManager::addListItem(MarkType typeMrk, QString typeStr, const QList<Mark*> &marks, int &index) +{ + bool noSuchMarks = true; + QTreeWidgetItem *listItem = new QTreeWidgetItem(listView); + listItem->setText(0,typeStr); + listItem->setFlags(listItem->flags() & (~Qt::ItemIsSelectable)); + listItem->setBackground(0,QColor("lightGray")); + for (int i = 0; i < marks.size(); ++i) + { + if (marks[i]->isType(typeMrk)) + { + QTreeWidgetItem *listItem2 = new QTreeWidgetItem(listItem); + listItem2->setText(0, marks[i]->label); + listItem2->setData(1, Qt::UserRole,QVariant::fromValue<void*>(marks[i])); + index++; + noSuchMarks = false; + } + } + if (noSuchMarks) + { + listView->removeItemWidget(listItem,0); + delete listItem; + } + else + listItem->sortChildren(0, Qt::AscendingOrder); +} + +void MarksManager::storeColaption() +{ + expandedItems.clear(); + for (int i=0; i < listView->topLevelItemCount(); ++i) + { + QTreeWidgetItem *item = listView->topLevelItem(i); + if (item->isExpanded()) + expandedItems.append(item->text(0)); + } +} + +void MarksManager::restoreColaption() +{ + listView->collapseAll(); + if (!expandedItems.isEmpty()) + { + for (int i=0; i < listView->topLevelItemCount(); ++i) + { + QTreeWidgetItem *item = listView->topLevelItem(i); + if (expandedItems.contains(item->text(0))) + listView->topLevelItem(i)->setExpanded(true); + } + } +} + +void MarksManager::updateListView() +{ + storeColaption(); + listView->clear(); + if (m_Doc == NULL) + return; + if (m_Doc->marksList().isEmpty()) + UpdateButton->setEnabled(false); + else + { + UpdateButton->setEnabled(true); + int index = 0; + addListItem(MARKAnchorType, tr("Anchors"), m_Doc->marksList(), index); + addListItem(MARKVariableTextType, tr("Variable Text"), m_Doc->marksList(), index); + addListItem(MARK2ItemType, tr("Marks to Items"), m_Doc->marksList(), index); + addListItem(MARK2MarkType, tr("Marks to Anchors"), m_Doc->marksList(), index); + addListItem(MARKNoteMasterType, tr("Notes marks"), m_Doc->marksList(), index); + // addListItem(MARKIndexType, tr("Index entries");, marks, index); + listView->sortByColumn(0); + } + restoreColaption(); + m_Doc->flag_updateMarksLabels = false; + m_Doc->flag_updateEndNotes = false; +} + +void MarksManager::setDoc(ScribusDoc *doc) +{ + if (m_Doc != NULL) + disconnect(m_Doc->scMW(), SIGNAL(UpdateRequest(int)), this , SLOT(handleUpdateRequest(int))); + bool hasDoc = (doc != NULL); + m_Doc = doc; + if (hasDoc) + { + UpdateButton->setEnabled(true); + listView->setEnabled(true); + updateListView(); + connect(m_Doc->scMW(), SIGNAL(UpdateRequest(int)), this , SLOT(handleUpdateRequest(int))); + } + else + listView->clear(); +} + +void MarksManager::languageChange() +{ + setWindowTitle(tr("Marks Manager")); + listView->setToolTip(tr("Double click to find mark in text")); + UpdateButton->setText(tr("Update All Marks")); + UpdateButton->setToolTip(tr("Update all refeence texts for all marks")); + EditButton->setText(tr("Edit")); + EditButton->setToolTip(tr("Edit selected mark")); + if (m_Doc != NULL) + updateListView(); +} + +void MarksManager::handleUpdateRequest(int updateFlags) +{ + if (updateFlags & reqMarksUpdate) { + updateListView(); + } + m_Doc->flag_updateMarksLabels = false; +} + +Mark* MarksManager::getMarkFromListView() +{ + QTreeWidgetItem* selectedItem = listView->currentItem(); + if (selectedItem == NULL) + return NULL; + Mark* mrk = reinterpret_cast<Mark*>(selectedItem->data(1, Qt::UserRole).value<void*>()); + return mrk; +} + +void MarksManager::on_UpdateButton_clicked() +{ + m_Doc->flag_updateMarksLabels = true; + m_Doc->flag_updateEndNotes = true; + m_Doc->setNotesChanged(true); + if (m_Doc->updateMarks(true)) + { + m_Doc->changed(); + m_Doc->regionsChanged()->update(QRectF()); + updateListView(); + } + + //update lables for "lost" marks (marks not in any text) + QList<Mark*> notUsed; + for (int a=0; a < m_Doc->marksList().count(); ++a) + { + Mark* mrk = m_Doc->marksList().at(a); + if (mrk->isUnique() && !mrk->label.startsWith("UNVISIBLE*") && !m_Doc->isMarkUsed(mrk, true)) + notUsed.append(mrk); + } + if (!notUsed.isEmpty()) + { + for (int a=0; a<notUsed.count(); ++a) + { + Mark* mrk = notUsed.at(a); + QString l = "UNVISIBLE*" + mrk->label; + getUniqueName(l,m_Doc->marksLabelsList(mrk->getType()),"_"); + mrk->label = l; + } + updateListView(); + } +} + +void MarksManager::on_EditButton_clicked() +{ + Mark* mrk = getMarkFromListView(); + if (mrk != NULL) + { + if (m_Doc->scMW()->editMarkDlg(mrk)) + { + if (mrk->isType(MARKVariableTextType)) + m_Doc->flag_updateMarksLabels = true; +// else +// currItem->invalid = true; + m_Doc->changed(); + m_Doc->regionsChanged()->update(QRectF()); + updateListView(); + } + } +} + +void MarksManager::on_DeleteButton_clicked() +{ + Mark* mrk = getMarkFromListView(); + if (mrk != NULL) + { + if (mrk->isType(MARKNoteMasterType)) + m_Doc->setUndoDelNote(mrk->getNotePtr()); + else + m_Doc->setUndoDelMark(mrk); + m_Doc->eraseMark(mrk, true, NULL, true); + m_Doc->changed(); + m_Doc->regionsChanged()->update(QRectF()); + updateListView(); + } +} + +void MarksManager::on_listView_doubleClicked(const QModelIndex &index) +{ + Mark* mrk = getMarkFromListView(); + if (mrk != NULL) + m_Doc->setCursor2MarkPos(mrk); +} + +void MarksManager::on_listView_itemSelectionChanged() +{ + bool isMark = (getMarkFromListView() != NULL); + EditButton->setEnabled(isMark); + DeleteButton->setEnabled(isMark); +} diff --git Scribus/scribus/ui/marksmanager.h Scribus/scribus/ui/marksmanager.h new file mode 100644 index 0000000..53c1c47 --- /dev/null +++ Scribus/scribus/ui/marksmanager.h @@ -0,0 +1,42 @@ +#ifndef MARKSMANAGER_H +#define MARKSMANAGER_H + +#include <QList> +#include <QTreeWidgetItem> +#include "ui/scrpalettebase.h" +#include "ui_marksmanager.h" +#include "marks.h" +class QEvent; +class ScribusDoc; + +class SCRIBUS_API MarksManager : public ScrPaletteBase, Ui::MarksManager +{ + Q_OBJECT + +public: + explicit MarksManager(QWidget *parent = 0, const char *name = "MarksManager"); + ~MarksManager(); + void updateListView(); +private: + ScribusDoc *m_Doc; + PrefsContext *m_prefs; + Mark* getMarkFromListView(); + void addListItem(MarkType typeMrk, QString typeStr, const QList<Mark *> &marks, int &index); + QStringList expandedItems; + void storeColaption(); + void restoreColaption(); + +public slots: + void setDoc(ScribusDoc *doc); + void languageChange(); + void handleUpdateRequest(int updateFlags); + +private slots: + void on_UpdateButton_clicked(); + void on_EditButton_clicked(); + void on_DeleteButton_clicked(); + void on_listView_doubleClicked(const QModelIndex &index); + void on_listView_itemSelectionChanged(); +}; + +#endif // MARKSMANAGER_H diff --git Scribus/scribus/ui/marksmanager.ui Scribus/scribus/ui/marksmanager.ui new file mode 100644 index 0000000..c166897 --- /dev/null +++ Scribus/scribus/ui/marksmanager.ui @@ -0,0 +1,90 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>MarksManager</class> + <widget class="QDialog" name="MarksManager"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>253</width> + <height>249</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>200</width> + <height>100</height> + </size> + </property> + <property name="windowTitle"> + <string>Dialog</string> + </property> + <property name="modal"> + <bool>false</bool> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="1" column="0"> + <widget class="QPushButton" name="UpdateButton"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Update All Marks</string> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QSplitter" name="splitter"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <widget class="QPushButton" name="EditButton"> + <property name="text"> + <string>Edit</string> + </property> + </widget> + <widget class="QPushButton" name="DeleteButton"> + <property name="text"> + <string>Delete</string> + </property> + </widget> + </widget> + </item> + <item row="0" column="0"> + <widget class="QTreeWidget" name="listView"> + <property name="editTriggers"> + <set>QAbstractItemView::DoubleClicked</set> + </property> + <property name="showDropIndicator" stdset="0"> + <bool>false</bool> + </property> + <property name="selectionMode"> + <enum>QAbstractItemView::NoSelection</enum> + </property> + <property name="selectionBehavior"> + <enum>QAbstractItemView::SelectItems</enum> + </property> + <property name="horizontalScrollMode"> + <enum>QAbstractItemView::ScrollPerPixel</enum> + </property> + <column> + <property name="text"> + <string notr="true">1</string> + </property> + </column> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git Scribus/scribus/ui/markvariabletext.cpp Scribus/scribus/ui/markvariabletext.cpp new file mode 100644 index 0000000..05f2cfa --- /dev/null +++ Scribus/scribus/ui/markvariabletext.cpp @@ -0,0 +1,95 @@ +#include "markvariabletext.h" +#include "marks.h" +#include <QComboBox> + +MarkVariableTextDlg::MarkVariableTextDlg(const QList<Mark*>& marks, QWidget *parent) : MarkInsertDlg(marks, parent) +{ + //for editing mark entry in text - user can change mark pointer inserted into text or create new mark entry + setupUi(this); + + labelEditWidget = (QWidget*) new QComboBox(parent); + ((QComboBox*) labelEditWidget)->addItem(tr("New Mark"), QVariant::fromValue((void*) NULL)); + for (int i = 0; i < marks.size(); ++i) + { + if (marks[i]->isType(MARKVariableTextType)) + ((QComboBox*) labelEditWidget)->addItem(marks[i]->label, QVariant::fromValue((void*) marks[i])); + } + ((QComboBox*) labelEditWidget)->setEditable(true); + ((QComboBox*) labelEditWidget)->lineEdit()->setToolTip(tr("Edit selected Mark`s label. To create new Mark select \"New Mark\" in drop list and input new label")); + connect(((QComboBox*) labelEditWidget), SIGNAL(currentIndexChanged(int)),this,SLOT(onLabelList_currentIndexChanged(int))); + labelLayout->addWidget(labelEditWidget); + textEdit->setToolTip(tr("Edit variable text")); + setWindowTitle(tr("Mark with Variable Text")); +} + +MarkVariableTextDlg::MarkVariableTextDlg(const Mark* mark, QWidget *parent) : MarkInsertDlg(mark, parent), mrk(mark) +{ + //for editing by marks Manager - user can change label and variable text + setupUi(this); + + labelEditWidget = (QWidget*) new QLineEdit(parent); + ((QLineEdit*) labelEditWidget)->setToolTip(tr("Edit selected Mark`s label.")); + + labelLayout->addWidget(labelEditWidget); + textEdit->setToolTip(tr("Edit variable text")); + setWindowTitle(tr("Mark with Variable Text")); +} + +MarkVariableTextDlg::~MarkVariableTextDlg() +{ + //delete ui; + delete labelEditWidget; +} + +Mark* MarkVariableTextDlg::values(QString& label, QString& text) +{ + text = textEdit->text(); + //hack to read if it is QComboBox or QLineEdit + if (labelEditWidget->toolTip() != tr("Edit selected Mark`s label.")) + { + int labelID = ((QComboBox*) labelEditWidget)->currentIndex(); + label = ((QComboBox*) labelEditWidget)->currentText(); + if (label == tr("New Mark")) + label = "VariableMark"; + return (Mark*) ((QComboBox*) labelEditWidget)->itemData(labelID).value<void*>(); + } + label = ((QLineEdit*) labelEditWidget)->text(); + if (label == tr("New Mark")) + label = "VariableMark"; + return const_cast<Mark*> (mrk); +} + +void MarkVariableTextDlg::setValues(QString label, QString text) +{ + if (labelEditWidget->toolTip() == tr("Edit selected Mark`s label.")) + ((QLineEdit*) labelEditWidget)->setText(label); + else + ((QComboBox*) labelEditWidget)->setCurrentIndex(((QComboBox*) labelEditWidget)->findText(label)); + textEdit->setText(text); +} + +void MarkVariableTextDlg::changeEvent(QEvent *e) +{ + QDialog::changeEvent(e); + switch (e->type()) { + case QEvent::LanguageChange: + retranslateUi(this); + break; + default: + break; + } +} + +void MarkVariableTextDlg::onLabelList_currentIndexChanged(int index) +{ + if (index > 0) + { + Mark* mrk = (Mark*) ((QComboBox*) labelEditWidget)->itemData(index).value<void*>(); + textEdit->setText(mrk->getString()); + } + else + { + ((QComboBox*) labelEditWidget)->setEditText(""); + textEdit->clear(); + } +} diff --git Scribus/scribus/ui/markvariabletext.h Scribus/scribus/ui/markvariabletext.h new file mode 100644 index 0000000..edbbd0b --- /dev/null +++ Scribus/scribus/ui/markvariabletext.h @@ -0,0 +1,26 @@ +#ifndef MARKVARIABLETEXT_H +#define MARKVARIABLETEXT_H + +#include "scribusapi.h" +#include "MarkInsertDlg.h" +#include "ui_markvariabletext.h" + +class SCRIBUS_API MarkVariableTextDlg : public MarkInsertDlg, private Ui::MarkVariableTextDlg +{ + Q_OBJECT +public: + explicit MarkVariableTextDlg(const QList<Mark*>&, QWidget *parent = 0); + explicit MarkVariableTextDlg(const Mark*, QWidget *parent = 0); + ~MarkVariableTextDlg(); + virtual Mark* values(QString& label, QString& text); + virtual void setValues(const QString label, const QString text); +protected: + void changeEvent(QEvent *e); +private slots: + void onLabelList_currentIndexChanged(int index); +private: + QWidget* labelEditWidget; + const Mark* mrk; +}; + +#endif // MARKVARIABLETEXT_H diff --git Scribus/scribus/ui/markvariabletext.ui Scribus/scribus/ui/markvariabletext.ui new file mode 100644 index 0000000..861e05b --- /dev/null +++ Scribus/scribus/ui/markvariabletext.ui @@ -0,0 +1,130 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>MarkVariableTextDlg</class> + <widget class="QDialog" name="MarkVariableTextDlg"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>394</width> + <height>117</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>117</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>117</height> + </size> + </property> + <property name="windowTitle"> + <string>Add new Mark for Variable Text</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <layout class="QHBoxLayout" name="labelLayout"> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Label:</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Text to insert:</string> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="textEdit"/> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>202</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>MarkVariableTextDlg</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>MarkVariableTextDlg</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git Scribus/scribus/ui/notesstyleseditor.cpp Scribus/scribus/ui/notesstyleseditor.cpp new file mode 100644 index 0000000..ebfc705 --- /dev/null +++ Scribus/scribus/ui/notesstyleseditor.cpp @@ -0,0 +1,599 @@ +#include <QMessageBox> + +#include "notesstyleseditor.h" +#include "pageitem_noteframe.h" +#include "prefsmanager.h" +#include "prefsfile.h" +#include "scribusdoc.h" +#include "scribusview.h" +#include "scribus.h" +#include "scmessagebox.h" +#include "undomanager.h" + +NotesStylesEditor::NotesStylesEditor(QWidget *parent, const char *name) + : ScrPaletteBase(parent, name), m_Doc(NULL) +{ + setupUi(this); + QString pname(name); + if (pname.isEmpty()) + pname = "notesStylesEditor"; + m_prefs = PrefsManager::instance()->prefsFile->getContext(pname); + + setBlockSignals(true); + + setDoc(0); + languageChange(); + NSlistBox->setInsertPolicy(QComboBox::InsertAlphabetically); + + NumberingBox->addItem("1 2 3"); + NumberingBox->addItem("i ii iii"); + NumberingBox->addItem("I II III"); + NumberingBox->addItem("a b c"); + NumberingBox->addItem("A B C"); + NumberingBox->addItem("*"); + + RangeBox->addItem(tr("Document")); + RangeBox->addItem(tr("Section")); + RangeBox->addItem(tr("Story")); + RangeBox->addItem(tr("Page")); + RangeBox->addItem(tr("Frame")); + + StartSpinBox->setMinimum(1); + StartSpinBox->setMaximum(99999); + changesMap.clear(); + addNewNsMode = false; + + setBlockSignals(isVisible()); +} + +NotesStylesEditor::~NotesStylesEditor() +{ + storeVisibility(this->isVisible()); + storePosition(); + storeSize(); +} + +void NotesStylesEditor::languageChange() +{ + bool wasSignalsBlocked = signalsBlocked(); + setBlockSignals(true); + + if (addNewNsMode) + { + OKButton->setText(tr("Cancel")); + OKButton->setToolTip(tr("Dialog is in adding new notes style mode. After pressing Cancel button dialog will be switched into normal notes styles edit mode.")); + ApplyButton->setText(tr("Add Style")); + } + else + { + OKButton->setText("OK"); + OKButton->setToolTip(""); + ApplyButton->setText(tr("Apply")); + } + NewButton->setText(tr("Add New Style")); + NewButton->setToolTip(tr("New notes style will be add to document only after pressing Apply butoton.\nYou cannot switch to different notes style before you apply that new one or press Cancel button and exit from adding mode.")); + NewNameLabel->setText(tr("New Style Name")); + FootRadio->setText(tr("Footnotes")); + EndRadio->setText(tr("Endnotes")); + NumberingLabel->setText("Numbering"); + RangeLabel->setText(tr("Range")); + StartLabel->setText(tr("Start Number")); + PrefixLabel->setText(tr("Prefix")); + SuffixLabel->setText(tr("Suffix")); + SuperMasterLabel->setText(tr("Superscript in text")); + SuperNoteLabel->setText(tr("Superscript in notes")); + charStyleComboLabel->setText(tr("Mark`s Character Style")); + paraStyleComboLabel->setText(tr("Note`s Paragraph Style")); + AutoHLabel->setText(tr("Auto Height")); + AutoWLabel->setText(tr("Auto Width")); + AutoWeldLabel->setText(tr("Auto Welding")); + AutoRemoveLabel->setText(tr("Remove if empty")); + DeleteButton->setText(tr("Delete")); + setBlockSignals(wasSignalsBlocked); +} + +void NotesStylesEditor::setDoc(ScribusDoc *doc) +{ + bool wasSignalsBlocked = signalsBlocked(); + setBlockSignals(true); + if (m_Doc != NULL) + disconnect(m_Doc->scMW(), SIGNAL(UpdateRequest(int)), this , SLOT(handleUpdateRequest(int))); + m_Doc = doc; + paraStyleCombo->setDoc(m_Doc); + charStyleCombo->setDoc(m_Doc); + if (m_Doc != NULL) + { + updateNSList(); + NSlistBox->setCurrentIndex(0); + readNotesStyle(NSlistBox->currentText()); + setEnabled(true); + ApplyButton->setEnabled(false); + connect(m_Doc->scMW(), SIGNAL(UpdateRequest(int)), this , SLOT(handleUpdateRequest(int))); + } + else + { + changesMap.clear(); + NewNameEdit->clear(); + setEnabled(false); + } + setBlockSignals(wasSignalsBlocked); +} + +void NotesStylesEditor::handleUpdateRequest(int updateFlags) +{ + bool wasSignalsBlocked = signalsBlocked(); + setBlockSignals(true); + if ((updateFlags & reqCharStylesUpdate) || (updateFlags & reqTextStylesUpdate)) + charStyleCombo->updateFormatList(); + if ((updateFlags & reqParaStylesUpdate) || (updateFlags & reqTextStylesUpdate)) + paraStyleCombo->updateFormatList(); + readNotesStyle(NSlistBox->currentText()); + setBlockSignals(wasSignalsBlocked); +} + +void NotesStylesEditor::updateNSList() +{ + bool wasSignalsBlocked = signalsBlocked(); + NSlistBox->blockSignals(true); + if (m_Doc == NULL) + NSlistBox->setEnabled(false); + else + { + NSlistBox->clear(); + changesMap.clear(); + for (int a = 0; a < m_Doc->m_docNotesStylesList.count(); ++a) + { + NSlistBox->addItem(m_Doc->m_docNotesStylesList.at(a)->name()); + changesMap.insert(m_Doc->m_docNotesStylesList.at(a)->name(), *(m_Doc->m_docNotesStylesList.at(a))); + } + if (!m_Doc->m_docNotesStylesList.isEmpty()) + NSlistBox->setEnabled(true); + if (NSlistBox->currentText() != tr("default")) + DeleteButton->setEnabled(true); + else + DeleteButton->setEnabled(false); + } + NSlistBox->blockSignals(wasSignalsBlocked); + + DeleteButton->setEnabled(NSlistBox->currentText() != tr("default")); +} + +void NotesStylesEditor::setBlockSignals(bool block) +{ + foreach (QWidget* obj, findChildren<QWidget *>()) + { + obj->blockSignals(block); + } + paraStyleCombo->blockSignals(block); + charStyleCombo->blockSignals(block); +} + +void NotesStylesEditor::setNotesStyle(NotesStyle * NS) +{ + if (NS == NULL) + return; + bool wasSignalsBlocked = signalsBlocked(); + setBlockSignals(true); + NSlistBox->setCurrentIndex(NSlistBox->findText(NS->name())); + NewNameEdit->setText(NS->name()); + if (NS->name() == tr("default")) + NewNameEdit->setEnabled(false); + else + NewNameEdit->setEnabled(true); + FootRadio->setChecked(!NS->isEndNotes()); + if (NS->range() == NSRframe) + EndRadio->setEnabled(false); + else + EndRadio->setEnabled(true); + EndRadio->setChecked(NS->isEndNotes()); + NumberingBox->setCurrentIndex((int) NS->getType()); + RangeBox->setCurrentIndex((int) NS->range()); + StartSpinBox->setValue(NS->start()); + PrefixEdit->setText(NS->prefix()); + SuffixEdit->setText(NS->suffix()); + SuperMasterCheck->setChecked(NS->isSuperscriptInMaster()); + SuperNoteCheck->setChecked(NS->isSuperscriptInNote()); + if (!NS->notesParStyle().isEmpty() && (NS->notesParStyle() != tr("No Style"))) + paraStyleCombo->setCurrentIndex(paraStyleCombo->findText(NS->notesParStyle())); + if (!NS->marksChStyle().isEmpty() && (NS->marksChStyle() != tr("No Style"))) + charStyleCombo->setCurrentIndex(charStyleCombo->findText(NS->marksChStyle())); + AutoH->setChecked(NS->isAutoNotesHeight()); + AutoW->setChecked(NS->isAutoNotesWidth()); + AutoWeld->setChecked(NS->isAutoWeldNotesFrames()); + //for endnotes remove FRAME range (same effect as footnotes for frame) + //and disable autofixing size of notes frames + int rangeFrameIndex = RangeBox->findText(tr("Frame")); + if (NS->isEndNotes()) + { + AutoW->setEnabled(false); + AutoWeld->setEnabled(false); + if (rangeFrameIndex >= 0) + RangeBox->removeItem(rangeFrameIndex); + } + else + { + AutoW->setEnabled(true); + AutoWeld->setEnabled(true); + if (rangeFrameIndex == -1) + RangeBox->addItem(tr("Frame")); + } + AutoRemove->setChecked(NS->isAutoRemoveEmptyNotesFrames()); + + ApplyButton->setEnabled(false); + setBlockSignals(wasSignalsBlocked); +} + +void NotesStylesEditor::readNotesStyle(QString nsName) +{ + NotesStyle * NS = m_Doc->getNotesStyle(nsName); + setNotesStyle(NS); +} + +void NotesStylesEditor::on_NSlistBox_currentIndexChanged(const QString &arg1) +{ + if (arg1 != tr("default")) + DeleteButton->setEnabled(true); + else + DeleteButton->setEnabled(false); + readNotesStyle(arg1); +} + +void NotesStylesEditor::on_ApplyButton_clicked() +{ + if (addNewNsMode) + { + QString newName = NSlistBox->currentText(); + NotesStyle newNS = changesMap.value(newName); + if (m_Doc->validateNSet(newNS)) + { + addNewNsMode = false; + OKButton->setText(tr("OK")); + OKButton->setToolTip(""); + ApplyButton->setText(tr("Apply")); + m_Doc->newNotesStyle(newNS); + updateNSList(); + NSlistBox->setCurrentIndex(NSlistBox->findText(newNS.name())); + } + else + return; + } + else + { + //remeber current NStyle + QString currNS = NSlistBox->currentText(); + NotesStyle* NS = NULL; + + foreach (const QString &nsName, changesMap.keys()) + { + NotesStyle n = changesMap.value(nsName); + + //validate settings + if (!m_Doc->validateNSet(n)) + { + NSlistBox->setCurrentIndex(NSlistBox->findText(n.name())); + break; + } + //rename + if (nsName != n.name()) + { + //new name for existing set + QString newName = n.name(); + getUniqueName(newName, changesMap.keys(),"="); + n.setName(newName); + NewNameEdit->setText(newName); + //current NSet name change + if (currNS == nsName) + currNS = newName; + NS = m_Doc->getNotesStyle(nsName); + m_Doc->renameNotesStyle(NS, newName); + m_Doc->setNotesChanged(true); + } + //change settings and update marks + NS = m_Doc->getNotesStyle(n.name()); + Q_ASSERT(NS != NULL); + if (*NS != n) + { + SimpleState* ss = NULL; + if (UndoManager::instance()->undoEnabled()) + { + ss = new SimpleState(UndoManager::EditNotesStyle); + ss->set("NSTYLE", QString("edit")); + m_Doc->undoSetNotesStyle(ss, NS); + } + //converting foot <--> end notes or changing footnotes range + if ((NS->isEndNotes() != n.isEndNotes()) || (NS->isEndNotes() && n.isEndNotes() && NS->range() != n.range())) + { + foreach (PageItem_NoteFrame* nF, m_Doc->listNotesFrames(NS)) + m_Doc->delNoteFrame(nF, false); + if (n.isEndNotes()) + m_Doc->flag_updateEndNotes = true; + } + m_Doc->setNotesChanged(true); //notesframes width must be updated + *NS = n; + if (ss) + { + ss->set("NEWname", NS->name()); + ss->set("NEWstart", NS->start()); + ss->set("NEWendNotes", NS->isEndNotes()); + ss->set("NEWnumStyle", (int) NS->getType()); + ss->set("NEWrange", (int) NS->range()); + ss->set("NEWprefix", NS->prefix()); + ss->set("NEWsuffix", NS->suffix()); + ss->set("NEWautoH", NS->isAutoNotesHeight()); + ss->set("NEWautoW", NS->isAutoNotesWidth()); + ss->set("NEWautoWeld", NS->isAutoWeldNotesFrames()); + ss->set("NEWautoRemove", NS->isAutoRemoveEmptyNotesFrames()); + ss->set("NEWsuperMaster", NS->isSuperscriptInMaster()); + ss->set("NEWsuperNote", NS->isSuperscriptInNote()); + ss->set("NEWmarksChStyle", NS->marksChStyle()); + ss->set("NEWnotesParStyle", NS->notesParStyle()); + UndoManager::instance()->action(m_Doc, ss); + } + //invalidate all text frames with marks from current changed notes style + foreach (PageItem* item, m_Doc->DocItems) + { + if (item->isTextFrame() && !item->isNoteFrame() && item->asTextFrame()->hasMark(NS)) + item->invalid = true; + } + m_Doc->updateNotesNums(NS); + m_Doc->updateNotesFramesSettings(NS); + if (m_Doc->flag_updateEndNotes) + m_Doc->updateEndnotesFrames(NS); + m_Doc->updateNotesFramesStyles(NS); + } + } + if (m_Doc->notesChanged()) + { + updateNSList(); + m_Doc->flag_updateMarksLabels = true; + m_Doc->changed(); + m_Doc->regionsChanged()->update(QRectF()); + } + //restore NStyle index + readNotesStyle(currNS); + } + + ApplyButton->setEnabled(false); + NSlistBox->setEnabled(true); + NewButton->setEnabled(true); +} + +void NotesStylesEditor::on_DeleteButton_clicked() +{ + QString nsName = NSlistBox->currentText(); + int t = ScMessageBox::warning(m_Doc->scMW(), QObject::tr("Attention! Deleting Notes Style"), "<qt>" + + QObject::tr("You are going to delete notes style %1, but you must to know, that it deletes all notes inputs in notes frames and notes marks in text with that notes style.").arg(nsName) + "</qt>", + QMessageBox::Ok, QMessageBox::Abort | QMessageBox::Default); + if (t == QMessageBox::Ok) + { + m_Doc->deleteNotesStyle(nsName); + m_Doc->changed(); + m_Doc->regionsChanged()->update(QRectF()); + setDoc(m_Doc); + } +} + +void NotesStylesEditor::on_NewButton_clicked() +{ + QString oldName = NSlistBox->currentText(); + NotesStyle newNS = changesMap.value(oldName); + QString newName = oldName; + getUniqueName(newName, changesMap.keys(), "_"); + newNS.setName(newName); + changesMap.insert(newName, newNS); + setNotesStyle(&newNS); + + NewNameEdit->setEnabled(true); + NSlistBox->addItem(newName); + NSlistBox->setCurrentIndex(NSlistBox->findText(newName)); + NSlistBox->setEnabled(false); + ApplyButton->setText(tr("Add Style")); + ApplyButton->setEnabled(true); + DeleteButton->setEnabled(false); + NewButton->setEnabled(false); + addNewNsMode = true; + OKButton->setText(tr("Cancel Adding")); + OKButton->setToolTip(tr("Notes Styles Editor is in adding new notes style mode. After pressing Cancel button Notes Styles Editor switch into normal notes styles edit mode.")); +} + +void NotesStylesEditor::on_OKButton_clicked() +{ + if (OKButton->text() != tr("OK")) + { + //in adding new style mode go back to normal editing mode + OKButton->setText(tr("OK")); + NewButton->setEnabled(true); + addNewNsMode = false; + QString newName = NSlistBox->currentText(); + changesMap.remove(newName); + int index = NSlistBox->findText(newName); + NSlistBox->removeItem(index); + NSlistBox->setCurrentIndex(index-1); + on_NSlistBox_currentIndexChanged(NSlistBox->currentText()); + } + else + { + if (ApplyButton->isEnabled()) + //apply changes + on_ApplyButton_clicked(); + + //in normal mode close + close(); + } +} + +void NotesStylesEditor::on_NewNameEdit_textChanged(const QString &arg1) +{ + NotesStyle ns = changesMap.value(NSlistBox->currentText()); + ns.setName(arg1); + changesMap.insert(NSlistBox->currentText(), ns); + ApplyButton->setEnabled(true); +} + +void NotesStylesEditor::on_FootRadio_toggled(bool checked) +{ + bool wasSignalsBlocked = signalsBlocked(); + setBlockSignals(true); + + NotesStyle ns = changesMap.value(NSlistBox->currentText()); + ns.setEndNotes(!checked); + changesMap.insert(NSlistBox->currentText(), ns); + EndRadio->setChecked(!checked); + if (checked) + { + ns.setAutoNotesWidth(true); + AutoW->setEnabled(true); + AutoW->setChecked(true); + ns.setAutoWeldNotesFrames(true); + AutoWeld->setEnabled(true); + AutoWeld->setChecked(true); + } + + changesMap.insert(NSlistBox->currentText(), ns); + ApplyButton->setEnabled(true); + setBlockSignals(wasSignalsBlocked); +} + +void NotesStylesEditor::on_EndRadio_toggled(bool checked) +{ + bool wasSignalsBlocked = signalsBlocked(); + setBlockSignals(true); + + NotesStyle ns = changesMap.value(NSlistBox->currentText()); + ns.setEndNotes(checked); + FootRadio->setChecked(!checked); + if (checked) + { + ns.setAutoNotesWidth(false); + AutoW->setChecked(false); + AutoW->setEnabled(false); + ns.setAutoWeldNotesFrames(false); + AutoWeld->setChecked(false); + AutoWeld->setEnabled(false); + } + + changesMap.insert(NSlistBox->currentText(), ns); + ApplyButton->setEnabled(true); + setBlockSignals(wasSignalsBlocked); +} + +void NotesStylesEditor::on_NumberingBox_currentIndexChanged(int index) +{ + NotesStyle ns = changesMap.value(NSlistBox->currentText()); + ns.setType((NumerationType) index); + + changesMap.insert(NSlistBox->currentText(), ns); + ApplyButton->setEnabled(true); +} + +void NotesStylesEditor::on_RangeBox_currentIndexChanged(int index) +{ + NotesStyle ns = changesMap.value(NSlistBox->currentText()); + ns.setRange((NumerationRange) index); + + changesMap.insert(NSlistBox->currentText(), ns); + ApplyButton->setEnabled(true); +} + +void NotesStylesEditor::on_StartSpinBox_valueChanged(int arg1) +{ + NotesStyle ns = changesMap.value(NSlistBox->currentText()); + ns.setStart(arg1); + + changesMap.insert(NSlistBox->currentText(), ns); + ApplyButton->setEnabled(true); +} + +void NotesStylesEditor::on_PrefixEdit_textChanged(const QString &arg1) +{ + NotesStyle ns = changesMap.value(NSlistBox->currentText()); + ns.setPrefix(arg1); + + changesMap.insert(NSlistBox->currentText(), ns); + ApplyButton->setEnabled(true); +} + +void NotesStylesEditor::on_SuffixEdit_textChanged(const QString &arg1) +{ + NotesStyle ns = changesMap.value(NSlistBox->currentText()); + ns.setSuffix(arg1); + + changesMap.insert(NSlistBox->currentText(), ns); + ApplyButton->setEnabled(true); +} + +void NotesStylesEditor::on_SuperMasterCheck_toggled(bool checked) +{ + NotesStyle ns = changesMap.value(NSlistBox->currentText()); + ns.setSuperscriptInMaster(checked); + + changesMap.insert(NSlistBox->currentText(), ns); + ApplyButton->setEnabled(true); +} + +void NotesStylesEditor::on_SuperNoteCheck_toggled(bool checked) +{ + NotesStyle ns = changesMap.value(NSlistBox->currentText()); + ns.setSuperscriptInNote(checked); + + changesMap.insert(NSlistBox->currentText(), ns); + ApplyButton->setEnabled(true); +} + +void NotesStylesEditor::on_AutoH_toggled(bool checked) +{ + NotesStyle ns = changesMap.value(NSlistBox->currentText()); + ns.setAutoNotesHeight(checked); + + changesMap.insert(NSlistBox->currentText(), ns); + ApplyButton->setEnabled(true); +} + +void NotesStylesEditor::on_AutoW_toggled(bool checked) +{ + NotesStyle ns = changesMap.value(NSlistBox->currentText()); + ns.setAutoNotesWidth(checked); + + changesMap.insert(NSlistBox->currentText(), ns); + ApplyButton->setEnabled(true); +} + +void NotesStylesEditor::on_AutoWeld_toggled(bool checked) +{ + NotesStyle ns = changesMap.value(NSlistBox->currentText()); + ns.setAutoWeldNotesFrames(checked); + + changesMap.insert(NSlistBox->currentText(), ns); + ApplyButton->setEnabled(true); +} + +void NotesStylesEditor::on_AutoRemove_toggled(bool checked) +{ + NotesStyle ns = changesMap.value(NSlistBox->currentText()); + ns.setAutoRemoveEmptyNotesFrames(checked); + + changesMap.insert(NSlistBox->currentText(), ns); + ApplyButton->setEnabled(true); +} + +void NotesStylesEditor::on_paraStyleCombo_currentIndexChanged(const int &arg1) +{ + NotesStyle ns = changesMap.value(NSlistBox->currentText()); + if (arg1 == 0) + ns.setNotesParStyle(""); + else + ns.setNotesParStyle(paraStyleCombo->itemText(arg1)); + changesMap.insert(NSlistBox->currentText(), ns); + ApplyButton->setEnabled(true); +} + +void NotesStylesEditor::on_charStyleCombo_currentIndexChanged(const int &arg1) +{ + NotesStyle ns = changesMap.value(NSlistBox->currentText()); + if (arg1 == 0) + ns.setMarksCharStyle(""); + else + ns.setMarksCharStyle(charStyleCombo->itemText(arg1)); + changesMap.insert(NSlistBox->currentText(), ns); + ApplyButton->setEnabled(true); +} diff --git Scribus/scribus/ui/notesstyleseditor.h Scribus/scribus/ui/notesstyleseditor.h new file mode 100644 index 0000000..fc07f88 --- /dev/null +++ Scribus/scribus/ui/notesstyleseditor.h @@ -0,0 +1,58 @@ +#ifndef NOTESSTYLESEDITOR_H +#define NOTESSTYLESEDITOR_H + +#include "notesstyles.h" +#include "ui/scrpalettebase.h" +#include "ui/spalette.h" +#include "ui_notesstyleseditor.h" +class ScribusDoc; +class ScribusMainWindow; + +class SCRIBUS_API NotesStylesEditor : public ScrPaletteBase, private Ui::NotesStylesEditor +{ + Q_OBJECT + +public: + explicit NotesStylesEditor(QWidget *parent = 0, const char *name = "notesStylesEditor"); + ~NotesStylesEditor(); + void updateNSList(); + +private: + ScribusDoc *m_Doc; + PrefsContext *m_prefs; + QMap<QString, NotesStyle> changesMap; //<NSname to change, NSet new values> + void readNotesStyle(QString nsName); + void changeNotesStyle(); + void setBlockSignals(bool block); + bool addNewNsMode; + +public slots: + void setDoc(ScribusDoc *doc); + void handleUpdateRequest(int updateFlags); + void languageChange(); + void setNotesStyle(NotesStyle* NS); + +private slots: + void on_NSlistBox_currentIndexChanged(const QString &arg1); + void on_ApplyButton_clicked(); + void on_DeleteButton_clicked(); + void on_OKButton_clicked(); + void on_NewNameEdit_textChanged(const QString &arg1); + void on_FootRadio_toggled(bool checked); + void on_EndRadio_toggled(bool checked); + void on_NumberingBox_currentIndexChanged(int index); + void on_RangeBox_currentIndexChanged(int index); + void on_StartSpinBox_valueChanged(int arg1); + void on_PrefixEdit_textChanged(const QString &arg1); + void on_SuffixEdit_textChanged(const QString &arg1); + void on_SuperMasterCheck_toggled(bool checked); + void on_SuperNoteCheck_toggled(bool checked); + void on_AutoH_toggled(bool checked); + void on_AutoW_toggled(bool checked); + void on_AutoWeld_toggled(bool checked); + void on_AutoRemove_toggled(bool checked); + void on_NewButton_clicked(); + void on_paraStyleCombo_currentIndexChanged(const int &arg1); + void on_charStyleCombo_currentIndexChanged(const int &arg1); +}; +#endif // NOTESSTYLESEDITOR_H diff --git Scribus/scribus/ui/notesstyleseditor.ui Scribus/scribus/ui/notesstyleseditor.ui new file mode 100644 index 0000000..0fb92e4 --- /dev/null +++ Scribus/scribus/ui/notesstyleseditor.ui @@ -0,0 +1,376 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>NotesStylesEditor</class> + <widget class="QDialog" name="NotesStylesEditor"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>284</width> + <height>500</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>280</width> + <height>360</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>500</height> + </size> + </property> + <property name="windowTitle"> + <string>Notes Styles Editor</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="1" column="0"> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QComboBox" name="NSlistBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="NewButton"> + <property name="text"> + <string>Add New Style</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QFormLayout" name="formLayout"> + <property name="fieldGrowthPolicy"> + <enum>QFormLayout::AllNonFixedFieldsGrow</enum> + </property> + <property name="rowWrapPolicy"> + <enum>QFormLayout::DontWrapRows</enum> + </property> + <property name="labelAlignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <item row="0" column="0"> + <widget class="QLabel" name="NewNameLabel"> + <property name="text"> + <string>New Style Name</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLineEdit" name="NewNameEdit"/> + </item> + <item row="1" column="0"> + <widget class="QRadioButton" name="FootRadio"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Footnotes</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QRadioButton" name="EndRadio"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Endnotes</string> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="NumberingLabel"> + <property name="text"> + <string>Numbering</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QComboBox" name="NumberingBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="RangeLabel"> + <property name="text"> + <string>Range</string> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QComboBox" name="RangeBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> + <item row="4" column="0"> + <widget class="QLabel" name="StartLabel"> + <property name="text"> + <string>Start Number</string> + </property> + </widget> + </item> + <item row="4" column="1"> + <widget class="QSpinBox" name="StartSpinBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> + <item row="5" column="0"> + <widget class="QLabel" name="PrefixLabel"> + <property name="text"> + <string>Prefix</string> + </property> + </widget> + </item> + <item row="5" column="1"> + <widget class="QLineEdit" name="PrefixEdit"/> + </item> + <item row="6" column="0"> + <widget class="QLabel" name="SuffixLabel"> + <property name="text"> + <string>Suffix</string> + </property> + </widget> + </item> + <item row="6" column="1"> + <widget class="QLineEdit" name="SuffixEdit"/> + </item> + <item row="7" column="0"> + <widget class="QCheckBox" name="SuperMasterCheck"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item row="7" column="1"> + <widget class="QLabel" name="SuperMasterLabel"> + <property name="text"> + <string>Superscript in text</string> + </property> + </widget> + </item> + <item row="8" column="0"> + <widget class="QCheckBox" name="SuperNoteCheck"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item row="8" column="1"> + <widget class="QLabel" name="SuperNoteLabel"> + <property name="text"> + <string>Superscript in notes</string> + </property> + </widget> + </item> + <item row="9" column="0"> + <widget class="QLabel" name="charStyleComboLabel"> + <property name="lineWidth"> + <number>2</number> + </property> + <property name="text"> + <string>Mark`s Character Style</string> + </property> + <property name="textFormat"> + <enum>Qt::RichText</enum> + </property> + </widget> + </item> + <item row="9" column="1"> + <widget class="CharStyleComboBox" name="charStyleCombo"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> + <item row="10" column="0"> + <widget class="QLabel" name="paraStyleComboLabel"> + <property name="text"> + <string>Note`s Paragraph Style</string> + </property> + </widget> + </item> + <item row="10" column="1"> + <widget class="ParaStyleComboBox" name="paraStyleCombo"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> + <item row="11" column="0"> + <widget class="QCheckBox" name="AutoH"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item row="11" column="1"> + <widget class="QLabel" name="AutoHLabel"> + <property name="text"> + <string>Auto Height</string> + </property> + </widget> + </item> + <item row="12" column="0"> + <widget class="QCheckBox" name="AutoW"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item row="12" column="1"> + <widget class="QLabel" name="AutoWLabel"> + <property name="text"> + <string>Auto Width</string> + </property> + </widget> + </item> + <item row="13" column="0"> + <widget class="QCheckBox" name="AutoWeld"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item row="13" column="1"> + <widget class="QLabel" name="AutoWeldLabel"> + <property name="text"> + <string>Auto Welding</string> + </property> + </widget> + </item> + <item row="14" column="0"> + <widget class="QCheckBox" name="AutoRemove"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item row="14" column="1"> + <widget class="QLabel" name="AutoRemoveLabel"> + <property name="text"> + <string>Remove if empty</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QPushButton" name="ApplyButton"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Apply</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="DeleteButton"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Delete</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="OKButton"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>OK</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>CharStyleComboBox</class> + <extends>QComboBox</extends> + <header>ui/spalette.h</header> + </customwidget> + <customwidget> + <class>ParaStyleComboBox</class> + <extends>QComboBox</extends> + <header>ui/spalette.h</header> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git Scribus/scribus/undomanager.cpp Scribus/scribus/undomanager.cpp index 355f876..f076104 100644 --- Scribus/scribus/undomanager.cpp +++ Scribus/scribus/undomanager.cpp @@ -992,6 +992,15 @@ void UndoManager::languageChange() UndoManager::ImportText = tr("Import text"); UndoManager::ClearText = tr("Clear text"); UndoManager::AddLoremIpsum = tr("Add Lorem Ipsum"); + UndoManager::InsertMark = tr("Insert mark"); + UndoManager::InsertNote = tr("Insert note"); + UndoManager::EditMark = tr("Edit mark"); + UndoManager::DeleteMark = tr("Delete mark"); + UndoManager::DeleteNote = tr("Delete note"); + UndoManager::NewNotesStyle = tr("Add note style"); + UndoManager::EditNotesStyle = tr("Edit note style"); + UndoManager::DeleteNotesStyle = tr("Delete note style"); + UndoManager::DeleteNotesStyle = tr("Delete note style"); UndoManager::DeletePage = tr("Delete page"); UndoManager::DeletePages = tr("Delete pages"); UndoManager::ChangePageProps = tr("Change page properties"); @@ -1042,6 +1051,7 @@ void UndoManager::languageChange() UndoManager::PathOperation = tr("Path Operation"); UndoManager::ChangePageAttrs = tr("Change Page Attributes"); UndoManager::Transform = tr("Transform"); + UndoManager::WeldItems = tr("Weld Items"); } void UndoManager::initIcons() @@ -1255,6 +1265,14 @@ QString UndoManager::ClearText = ""; QString UndoManager::ReplaceText = ""; QString UndoManager::InsertText = ""; QString UndoManager::AddLoremIpsum = ""; +QString UndoManager::EditMark = ""; +QString UndoManager::InsertMark = ""; +QString UndoManager::DeleteMark = ""; +QString UndoManager::InsertNote = ""; +QString UndoManager::DeleteNote = ""; +QString UndoManager::NewNotesStyle = ""; +QString UndoManager::EditNotesStyle = ""; +QString UndoManager::DeleteNotesStyle = ""; QString UndoManager::DeletePage = ""; QString UndoManager::DeletePages = ""; QString UndoManager::ChangePageProps = ""; @@ -1305,6 +1323,7 @@ QString UndoManager::ClearImage = ""; QString UndoManager::PathOperation = ""; QString UndoManager::ChangePageAttrs = ""; QString UndoManager::Transform = ""; +QString UndoManager::WeldItems = ""; /*** Icons for UndoObjects *******************************************/ QPixmap *UndoManager::IImageFrame = 0; diff --git Scribus/scribus/undomanager.h Scribus/scribus/undomanager.h index 24e92df..99b5625 100644 --- Scribus/scribus/undomanager.h +++ Scribus/scribus/undomanager.h @@ -587,6 +587,14 @@ public: static QString AddLoremIpsum; static QString DeleteText; static QString InsertText; + static QString InsertMark; + static QString InsertNote; + static QString EditMark; + static QString DeleteMark; + static QString NewNotesStyle; + static QString EditNotesStyle; + static QString DeleteNotesStyle; + static QString DeleteNote; static QString DeletePage; static QString DeletePages; static QString ChangePageProps; @@ -652,6 +660,7 @@ public: static QString UnlinkTextFrame; static QString ClearImage; static QString PathOperation; + static QString WeldItems; /*@}*/ /** diff --git Scribus/scribus/undostate.h Scribus/scribus/undostate.h index 3d40892..7ece2b6 100644 --- Scribus/scribus/undostate.h +++ Scribus/scribus/undostate.h @@ -28,8 +28,10 @@ for which a new license (GPL+exception) is in place. #define UNDOSTATE_H #include <QMap> +#include <QPair> #include <QPixmap> #include <QVariant> +#include <QList> #include "scribusapi.h" #include "undoobject.h" @@ -295,5 +297,19 @@ public: private: C item_; }; +/**** ItemsState for list of pointers to items *****/ +//template<class C> +class ScItemsState : public SimpleState +{ +public: + ScItemsState(const QString& name, const QString& description = 0, QPixmap* pixmap = 0) + : SimpleState(name, description, pixmap) {} + ~ScItemsState() {} + void insertItem(QString itemname, void * item) { pointerMap.insert(itemname, item); } + void* getItem(QString itemname) const { if (pointerMap.contains(itemname)) return pointerMap.value(itemname); else return NULL;} + QList< QPair<void*, int> > insertItemPos; +private: + QMap<QString,void*> pointerMap; +}; #endif diff --git Scribus/scribus/util.cpp Scribus/scribus/util.cpp index 0eb0d5e..300dda8 100644 --- Scribus/scribus/util.cpp +++ Scribus/scribus/util.cpp @@ -537,7 +537,7 @@ QString getFileNameByPage(ScribusDoc* currDoc, uint pageNo, QString extension) return QString("%1-%2%3.%4").arg(defaultName).arg(QObject::tr("page", "page export")).arg(number, 3, 10, QChar('0')).arg(extension); } -const QString getStringFromSequence(DocumentSectionType type, uint position) +const QString getStringFromSequence(DocumentSectionType type, uint position, QString asterix) { QString retVal(""); switch( type ) @@ -559,6 +559,10 @@ const QString getStringFromSequence(DocumentSectionType type, uint position) //ie, X=10, x=10000 retVal=arabicToRoman(position).toLower(); break; + case Type_asterix: + for (uint a=1; a <= position; ++a) + retVal.append(asterix); + break; case Type_None: break; default: @@ -1124,3 +1128,19 @@ void convertOldTable(ScribusDoc *m_Doc, PageItem* gItem, QList<PageItem*> &gpL, } delete gItem; } + +void getUniqueName(QString &name, QStringList list, QString separator, bool prepend) +{ + if (!list.contains(name)) + return; + int token = -1; + QString newName; + do { + token++; + if (prepend) + newName = separator + QString::number(token) + " " + name; + else + newName = name + separator + QString::number(token); + } while (list.contains(newName)); + name = newName; +} diff --git Scribus/scribus/util.h Scribus/scribus/util.h index 05af300..c62da88 100644 --- Scribus/scribus/util.h +++ Scribus/scribus/util.h @@ -129,7 +129,9 @@ QString SCRIBUS_API getLongPathName(const QString & shortPath); */ QString SCRIBUS_API getFileNameByPage(ScribusDoc* currDoc, uint pageNo, QString extension); void SCRIBUS_API sDebug(QString message); -const QString SCRIBUS_API getStringFromSequence(DocumentSectionType type, uint position); +//asterix is QString used in numeration when number is presented as few chars, like *, **, *** etc +//default is '*' but can be used any string +const QString SCRIBUS_API getStringFromSequence(DocumentSectionType type, uint position, QString asterix="*"); const QString SCRIBUS_API arabicToRoman(uint i); const QString SCRIBUS_API numberToLetterSequence(uint i); void SCRIBUS_API parsePagesString(QString pages, std::vector<int>* pageNs, int sourcePageCount); @@ -152,4 +154,10 @@ void SCRIBUS_API getDashArray(int dashtype, double linewidth, QVector<float> void SCRIBUS_API printBacktrace(int nFrames); void SCRIBUS_API convertOldTable(ScribusDoc *m_Doc, PageItem* gItem, QList<PageItem*> &gpL, QStack< QList<PageItem*> > *groupStackT = NULL, QList<PageItem *> *target = NULL); +/*! + *\brief + * check if name exists in list + * if exist then seprator and numbers are pre/append to name while it will be unique +*/ +void SCRIBUS_API getUniqueName(QString &name, QStringList list, QString separator = "", bool prepend = false); #endif diff --git Scribus/scribus/util_text.cpp Scribus/scribus/util_text.cpp index 19431d8..49e31d9 100644 --- Scribus/scribus/util_text.cpp +++ Scribus/scribus/util_text.cpp @@ -18,6 +18,7 @@ for which a new license (GPL+exception) is in place. #include "scribusdoc.h" #include "util_text.h" +#include "serializer.h" int findParagraphStyle(ScribusDoc* doc, const ParagraphStyle& parStyle) { @@ -50,3 +51,18 @@ int findParagraphStyle(ScribusDoc* doc, const QString &name) assert(false); return -1; } + +StoryText desaxeString(ScribusDoc* doc, QString saxedString) +{ + assert(!saxedString.isEmpty()); + + Serializer* dig = doc->textSerializer(); + dig->parseMemory(saxedString.toStdString().c_str(), saxedString.length()); + + StoryText* story = dig->result<StoryText>(); + assert (story != NULL); + + StoryText res = *story; + delete story; + return res; +} diff --git Scribus/scribus/util_text.h Scribus/scribus/util_text.h index 8e43470..281a116 100644 --- Scribus/scribus/util_text.h +++ Scribus/scribus/util_text.h @@ -13,6 +13,7 @@ for which a new license (GPL+exception) is in place. #include "styles/charstyle.h" #include "styles/paragraphstyle.h" #include "scribusapi.h" +#include "text/storytext.h" class ScribusDoc; @@ -21,5 +22,7 @@ int SCRIBUS_API findParagraphStyle(ScribusDoc* doc, const ParagraphStyle& parSty int SCRIBUS_API findParagraphStyle(ScribusDoc* doc, const QString &name); #endif +// returns StoryText from saxed string +StoryText SCRIBUS_API desaxeString(ScribusDoc* doc, QString saxedString); #endif |
|
New diff file is uploaded. Git diff (for Craig) created from branch "footnotes" synced today with trunk. |
|
Committed, although the patch was not perfect. I think maybe git is not in sync with SVN |
|
i was really and happily surprised to find mark feature in today svn !!! great ! |
Date Modified | Username | Field | Change |
---|---|---|---|
2012-08-14 12:49 | cezaryece | New Issue | |
2012-08-14 12:49 | cezaryece | File Added: footnotes.diff | |
2012-08-17 08:06 | cezaryece | Note Added: 0028827 | |
2012-09-28 14:52 | ale | Summary | Patch with marks/footnotes feature => [PATCH] marks/footnotes feature |
2012-10-01 07:45 | ale | Note Added: 0029006 | |
2012-10-13 19:23 | cbradney | Note Added: 0029042 | |
2012-10-22 19:39 | cbradney | Note Added: 0029084 | |
2012-10-26 08:58 | cezaryece | File Deleted: footnotes.diff | |
2012-10-26 08:59 | cezaryece | File Added: footnotes.diff | |
2012-10-26 09:00 | cezaryece | Note Added: 0029098 | |
2012-10-27 16:02 | cbradney | Note Added: 0029104 | |
2012-10-27 16:02 | cbradney | Status | new => resolved |
2012-10-27 16:02 | cbradney | Fixed in Version | => 1.5.0svn |
2012-10-27 16:02 | cbradney | Resolution | open => fixed |
2012-10-27 16:02 | cbradney | Assigned To | => cbradney |
2012-10-31 13:15 | JLuc | Note Added: 0029136 | |
2012-11-13 20:23 | cbradney | Status | resolved => closed |
2015-09-17 20:08 | Kunda | Category | Story Editor / Text Frames => Story Ed/Txt Frames |
2015-09-17 20:12 | Kunda | Category | Story Ed/Txt Frames => Story Editor / Text Frames |