mirror of https://github.com/JakubMelka/PDF4QT.git
Issue #76: Basic functionality of outline editing
This commit is contained in:
parent
a29a35e029
commit
be0d02bb5c
|
@ -370,6 +370,17 @@ void PDFAction::fillActionList(std::vector<const PDFAction*>& actionList) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PDFAction::cloneActionList(const PDFAction* sourceAction)
|
||||||
|
{
|
||||||
|
if (sourceAction)
|
||||||
|
{
|
||||||
|
for (const auto& action : sourceAction->m_nextActions)
|
||||||
|
{
|
||||||
|
m_nextActions.push_back(action->clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PDFDestination PDFDestination::parse(const PDFObjectStorage* storage, PDFObject object)
|
PDFDestination PDFDestination::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||||
{
|
{
|
||||||
PDFDestination result;
|
PDFDestination result;
|
||||||
|
@ -711,6 +722,16 @@ QString PDFActionURI::getURIString() const
|
||||||
return QString::fromUtf8(m_URI);
|
return QString::fromUtf8(m_URI);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PDFActionURI::setURI(const QByteArray& newURI)
|
||||||
|
{
|
||||||
|
m_URI = newURI;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDFActionURI::setIsMap(bool newIsMap)
|
||||||
|
{
|
||||||
|
m_isMap = newIsMap;
|
||||||
|
}
|
||||||
|
|
||||||
void PDFActionGoTo::setDestination(const PDFDestination& destination)
|
void PDFActionGoTo::setDestination(const PDFDestination& destination)
|
||||||
{
|
{
|
||||||
m_destination = destination;
|
m_destination = destination;
|
||||||
|
@ -721,4 +742,153 @@ void PDFActionGoTo::setStructureDestination(const PDFDestination& structureDesti
|
||||||
m_structureDestination = structureDestination;
|
m_structureDestination = structureDestination;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PDFActionPtr PDFActionGoTo::clone() const
|
||||||
|
{
|
||||||
|
PDFActionGoTo* clonedAction = new PDFActionGoTo(getDestination(), getStructureDestination());
|
||||||
|
clonedAction->cloneActionList(this);
|
||||||
|
return PDFActionPtr(clonedAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFActionPtr PDFActionGoToR::clone() const
|
||||||
|
{
|
||||||
|
PDFActionGoToR* clonedAction = new PDFActionGoToR(getDestination(),
|
||||||
|
getStructureDestination(),
|
||||||
|
getFileSpecification(),
|
||||||
|
isNewWindow());
|
||||||
|
clonedAction->cloneActionList(this);
|
||||||
|
return PDFActionPtr(clonedAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFActionPtr PDFActionGoToE::clone() const
|
||||||
|
{
|
||||||
|
PDFActionGoToE* clonedAction = new PDFActionGoToE(getDestination(),
|
||||||
|
getFileSpecification(),
|
||||||
|
isNewWindow(),
|
||||||
|
getTarget());
|
||||||
|
clonedAction->cloneActionList(this);
|
||||||
|
return PDFActionPtr(clonedAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFActionPtr PDFActionGoToDp::clone() const
|
||||||
|
{
|
||||||
|
PDFActionGoToDp* clonedAction = new PDFActionGoToDp(getDocumentPart());
|
||||||
|
clonedAction->cloneActionList(this);
|
||||||
|
return PDFActionPtr(clonedAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFActionPtr PDFActionLaunch::clone() const
|
||||||
|
{
|
||||||
|
PDFActionLaunch* clonedAction = new PDFActionLaunch(getFileSpecification(), isNewWindow(), getWinSpecification());
|
||||||
|
clonedAction->cloneActionList(this);
|
||||||
|
return PDFActionPtr(clonedAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFActionPtr PDFActionThread::clone() const
|
||||||
|
{
|
||||||
|
PDFActionThread* clonedAction = new PDFActionThread(getFileSpecification(), getThread(), getBead());
|
||||||
|
clonedAction->cloneActionList(this);
|
||||||
|
return PDFActionPtr(clonedAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFActionPtr PDFActionURI::clone() const
|
||||||
|
{
|
||||||
|
PDFActionURI* clonedAction = new PDFActionURI(getURI(), isMap());
|
||||||
|
clonedAction->cloneActionList(this);
|
||||||
|
return PDFActionPtr(clonedAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFActionPtr PDFActionSound::clone() const
|
||||||
|
{
|
||||||
|
PDFActionSound* clonedAction = new PDFActionSound(*getSound(), getVolume(), isSynchronous(), isRepeat(), isMix());
|
||||||
|
clonedAction->cloneActionList(this);
|
||||||
|
return PDFActionPtr(clonedAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFActionPtr PDFActionMovie::clone() const
|
||||||
|
{
|
||||||
|
PDFActionMovie* clonedAction = new PDFActionMovie(getAnnotation(), getTitle(), getOperation());
|
||||||
|
clonedAction->cloneActionList(this);
|
||||||
|
return PDFActionPtr(clonedAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFActionPtr PDFActionHide::clone() const
|
||||||
|
{
|
||||||
|
PDFActionHide* clonedAction = new PDFActionHide(getAnnotations(), getFieldNames(), isHide());
|
||||||
|
clonedAction->cloneActionList(this);
|
||||||
|
return PDFActionPtr(clonedAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFActionPtr PDFActionNamed::clone() const
|
||||||
|
{
|
||||||
|
PDFActionNamed* clonedAction = new PDFActionNamed(getNamedActionType(), getCustomNamedAction());
|
||||||
|
clonedAction->cloneActionList(this);
|
||||||
|
return PDFActionPtr(clonedAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFActionPtr PDFActionSetOCGState::clone() const
|
||||||
|
{
|
||||||
|
PDFActionSetOCGState* clonedAction = new PDFActionSetOCGState(getStateChangeItems(), isRadioButtonsPreserved());
|
||||||
|
clonedAction->cloneActionList(this);
|
||||||
|
return PDFActionPtr(clonedAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFActionPtr PDFActionTransition::clone() const
|
||||||
|
{
|
||||||
|
PDFActionTransition* clonedAction = new PDFActionTransition(getTransition());
|
||||||
|
clonedAction->cloneActionList(this);
|
||||||
|
return PDFActionPtr(clonedAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFActionPtr PDFActionGoTo3DView::clone() const
|
||||||
|
{
|
||||||
|
PDFActionGoTo3DView* clonedAction = new PDFActionGoTo3DView(getAnnotation(), getView());
|
||||||
|
clonedAction->cloneActionList(this);
|
||||||
|
return PDFActionPtr(clonedAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFActionPtr PDFActionJavaScript::clone() const
|
||||||
|
{
|
||||||
|
PDFActionJavaScript* clonedAction = new PDFActionJavaScript(getJavaScript());
|
||||||
|
clonedAction->cloneActionList(this);
|
||||||
|
return PDFActionPtr(clonedAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFActionPtr PDFActionRichMediaExecute::clone() const
|
||||||
|
{
|
||||||
|
PDFActionRichMediaExecute* clonedAction = new PDFActionRichMediaExecute(getRichMediaAnnotation(),
|
||||||
|
getRichMediaInstance(),
|
||||||
|
getCommand(),
|
||||||
|
getArguments());
|
||||||
|
clonedAction->cloneActionList(this);
|
||||||
|
return PDFActionPtr(clonedAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFActionPtr PDFActionSubmitForm::clone() const
|
||||||
|
{
|
||||||
|
PDFActionSubmitForm* clonedAction = new PDFActionSubmitForm(getFieldScope(), getFieldList(), getUrl(), getCharset(), getFlags());
|
||||||
|
clonedAction->cloneActionList(this);
|
||||||
|
return PDFActionPtr(clonedAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFActionPtr PDFActionResetForm::clone() const
|
||||||
|
{
|
||||||
|
PDFActionResetForm* clonedAction = new PDFActionResetForm(getFieldScope(), getFieldList(), getFlags());
|
||||||
|
clonedAction->cloneActionList(this);
|
||||||
|
return PDFActionPtr(clonedAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFActionPtr PDFActionImportDataForm::clone() const
|
||||||
|
{
|
||||||
|
PDFActionImportDataForm* clonedAction = new PDFActionImportDataForm(getFile());
|
||||||
|
clonedAction->cloneActionList(this);
|
||||||
|
return PDFActionPtr(clonedAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFActionPtr PDFActionRendition::clone() const
|
||||||
|
{
|
||||||
|
PDFActionRendition* clonedAction = new PDFActionRendition(m_rendition, getAnnotation(), getOperation(), getJavaScript());
|
||||||
|
clonedAction->cloneActionList(this);
|
||||||
|
return PDFActionPtr(clonedAction);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace pdf
|
} // namespace pdf
|
||||||
|
|
|
@ -169,6 +169,12 @@ public:
|
||||||
/// Returns list of actions to be executed
|
/// Returns list of actions to be executed
|
||||||
std::vector<const PDFAction*> getActionList() const;
|
std::vector<const PDFAction*> getActionList() const;
|
||||||
|
|
||||||
|
/// Clone action
|
||||||
|
virtual PDFActionPtr clone() const = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void cloneActionList(const PDFAction* sourceAction);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static PDFActionPtr parseImpl(const PDFObjectStorage* storage, PDFObject object, std::set<PDFObjectReference>& usedReferences);
|
static PDFActionPtr parseImpl(const PDFObjectStorage* storage, PDFObject object, std::set<PDFObjectReference>& usedReferences);
|
||||||
|
|
||||||
|
@ -180,7 +186,7 @@ private:
|
||||||
/// Regular go-to action. Can contain also structure destinations, both regular page destination
|
/// Regular go-to action. Can contain also structure destinations, both regular page destination
|
||||||
/// and structure destination are present, because if structure destination fails, then
|
/// and structure destination are present, because if structure destination fails, then
|
||||||
/// page destination can be used as fallback resolution.
|
/// page destination can be used as fallback resolution.
|
||||||
class PDFActionGoTo : public PDFAction
|
class PDF4QTLIBSHARED_EXPORT PDFActionGoTo : public PDFAction
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit inline PDFActionGoTo(PDFDestination destination, PDFDestination structureDestination) :
|
explicit inline PDFActionGoTo(PDFDestination destination, PDFDestination structureDestination) :
|
||||||
|
@ -194,6 +200,8 @@ public:
|
||||||
void setDestination(const PDFDestination& destination);
|
void setDestination(const PDFDestination& destination);
|
||||||
void setStructureDestination(const PDFDestination& structureDestination);
|
void setStructureDestination(const PDFDestination& structureDestination);
|
||||||
|
|
||||||
|
virtual PDFActionPtr clone() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PDFDestination m_destination;
|
PDFDestination m_destination;
|
||||||
PDFDestination m_structureDestination;
|
PDFDestination m_structureDestination;
|
||||||
|
@ -218,6 +226,8 @@ public:
|
||||||
const PDFFileSpecification& getFileSpecification() const { return m_fileSpecification; }
|
const PDFFileSpecification& getFileSpecification() const { return m_fileSpecification; }
|
||||||
bool isNewWindow() const { return m_newWindow; }
|
bool isNewWindow() const { return m_newWindow; }
|
||||||
|
|
||||||
|
virtual PDFActionPtr clone() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PDFDestination m_destination;
|
PDFDestination m_destination;
|
||||||
PDFDestination m_structureDestination;
|
PDFDestination m_structureDestination;
|
||||||
|
@ -244,6 +254,8 @@ public:
|
||||||
bool isNewWindow() const { return m_newWindow; }
|
bool isNewWindow() const { return m_newWindow; }
|
||||||
const PDFObject& getTarget() const { return m_target; }
|
const PDFObject& getTarget() const { return m_target; }
|
||||||
|
|
||||||
|
virtual PDFActionPtr clone() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PDFDestination m_destination;
|
PDFDestination m_destination;
|
||||||
PDFFileSpecification m_fileSpecification;
|
PDFFileSpecification m_fileSpecification;
|
||||||
|
@ -262,6 +274,8 @@ public:
|
||||||
|
|
||||||
PDFObjectReference getDocumentPart() const { return m_documentPart; }
|
PDFObjectReference getDocumentPart() const { return m_documentPart; }
|
||||||
|
|
||||||
|
virtual PDFActionPtr clone() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PDFObjectReference m_documentPart;
|
PDFObjectReference m_documentPart;
|
||||||
};
|
};
|
||||||
|
@ -293,6 +307,8 @@ public:
|
||||||
const Win& getWinSpecification() const { return m_win; }
|
const Win& getWinSpecification() const { return m_win; }
|
||||||
bool isNewWindow() const { return m_newWindow; }
|
bool isNewWindow() const { return m_newWindow; }
|
||||||
|
|
||||||
|
virtual PDFActionPtr clone() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PDFFileSpecification m_fileSpecification;
|
PDFFileSpecification m_fileSpecification;
|
||||||
bool m_newWindow = false;
|
bool m_newWindow = false;
|
||||||
|
@ -319,6 +335,8 @@ public:
|
||||||
const Thread& getThread() const { return m_thread; }
|
const Thread& getThread() const { return m_thread; }
|
||||||
const Bead& getBead() const { return m_bead; }
|
const Bead& getBead() const { return m_bead; }
|
||||||
|
|
||||||
|
virtual PDFActionPtr clone() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PDFFileSpecification m_fileSpecification;
|
PDFFileSpecification m_fileSpecification;
|
||||||
Thread m_thread;
|
Thread m_thread;
|
||||||
|
@ -344,6 +362,11 @@ public:
|
||||||
/// to PDF specification, URI is UTF-8 encoded string.
|
/// to PDF specification, URI is UTF-8 encoded string.
|
||||||
QString getURIString() const;
|
QString getURIString() const;
|
||||||
|
|
||||||
|
virtual PDFActionPtr clone() const override;
|
||||||
|
|
||||||
|
void setURI(const QByteArray& newURI);
|
||||||
|
void setIsMap(bool newIsMap);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QByteArray m_URI;
|
QByteArray m_URI;
|
||||||
bool m_isMap;
|
bool m_isMap;
|
||||||
|
@ -370,6 +393,8 @@ public:
|
||||||
bool isRepeat() const { return m_isRepeat; }
|
bool isRepeat() const { return m_isRepeat; }
|
||||||
bool isMix() const { return m_isMix; }
|
bool isMix() const { return m_isMix; }
|
||||||
|
|
||||||
|
virtual PDFActionPtr clone() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PDFSound m_sound;
|
PDFSound m_sound;
|
||||||
PDFReal m_volume;
|
PDFReal m_volume;
|
||||||
|
@ -403,6 +428,8 @@ public:
|
||||||
const QString& getTitle() const { return m_title; }
|
const QString& getTitle() const { return m_title; }
|
||||||
Operation getOperation() const { return m_operation; }
|
Operation getOperation() const { return m_operation; }
|
||||||
|
|
||||||
|
virtual PDFActionPtr clone() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PDFObjectReference m_annotation;
|
PDFObjectReference m_annotation;
|
||||||
QString m_title;
|
QString m_title;
|
||||||
|
@ -420,12 +447,22 @@ public:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
explicit inline PDFActionHide(const std::vector<PDFObjectReference>& annotations, const std::vector<QString>& fieldNames, bool hide) :
|
||||||
|
m_annotations(annotations),
|
||||||
|
m_fieldNames(fieldNames),
|
||||||
|
m_hide(hide)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
virtual ActionType getType() const override { return ActionType::Hide; }
|
virtual ActionType getType() const override { return ActionType::Hide; }
|
||||||
|
|
||||||
const std::vector<PDFObjectReference>& getAnnotations() const { return m_annotations; }
|
const std::vector<PDFObjectReference>& getAnnotations() const { return m_annotations; }
|
||||||
const std::vector<QString>& getFieldNames() const { return m_fieldNames; }
|
const std::vector<QString>& getFieldNames() const { return m_fieldNames; }
|
||||||
bool isHide() const { return m_hide; }
|
bool isHide() const { return m_hide; }
|
||||||
|
|
||||||
|
virtual PDFActionPtr clone() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<PDFObjectReference> m_annotations;
|
std::vector<PDFObjectReference> m_annotations;
|
||||||
std::vector<QString> m_fieldNames;
|
std::vector<QString> m_fieldNames;
|
||||||
|
@ -451,11 +488,20 @@ public:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
explicit inline PDFActionNamed(NamedActionType namedActionType, const QByteArray& customNamedAction) :
|
||||||
|
m_namedActionType(namedActionType),
|
||||||
|
m_customNamedAction(customNamedAction)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
virtual ActionType getType() const override { return ActionType::Named; }
|
virtual ActionType getType() const override { return ActionType::Named; }
|
||||||
|
|
||||||
NamedActionType getNamedActionType() const { return m_namedActionType; }
|
NamedActionType getNamedActionType() const { return m_namedActionType; }
|
||||||
const QByteArray& getCustomNamedAction() const { return m_customNamedAction; }
|
const QByteArray& getCustomNamedAction() const { return m_customNamedAction; }
|
||||||
|
|
||||||
|
virtual PDFActionPtr clone() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NamedActionType m_namedActionType;
|
NamedActionType m_namedActionType;
|
||||||
QByteArray m_customNamedAction;
|
QByteArray m_customNamedAction;
|
||||||
|
@ -475,7 +521,7 @@ public:
|
||||||
using StateChangeItem = std::pair<SwitchType, PDFObjectReference>;
|
using StateChangeItem = std::pair<SwitchType, PDFObjectReference>;
|
||||||
using StateChangeItems = std::vector<StateChangeItem>;
|
using StateChangeItems = std::vector<StateChangeItem>;
|
||||||
|
|
||||||
explicit inline PDFActionSetOCGState(StateChangeItems&& stateChangeItems, bool isRadioButtonsPreserved) :
|
explicit inline PDFActionSetOCGState(StateChangeItems stateChangeItems, bool isRadioButtonsPreserved) :
|
||||||
m_items(qMove(stateChangeItems)),
|
m_items(qMove(stateChangeItems)),
|
||||||
m_isRadioButtonsPreserved(isRadioButtonsPreserved)
|
m_isRadioButtonsPreserved(isRadioButtonsPreserved)
|
||||||
{
|
{
|
||||||
|
@ -487,6 +533,8 @@ public:
|
||||||
const StateChangeItems& getStateChangeItems() const { return m_items; }
|
const StateChangeItems& getStateChangeItems() const { return m_items; }
|
||||||
bool isRadioButtonsPreserved() const { return m_isRadioButtonsPreserved; }
|
bool isRadioButtonsPreserved() const { return m_isRadioButtonsPreserved; }
|
||||||
|
|
||||||
|
virtual PDFActionPtr clone() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
StateChangeItems m_items;
|
StateChangeItems m_items;
|
||||||
bool m_isRadioButtonsPreserved;
|
bool m_isRadioButtonsPreserved;
|
||||||
|
@ -505,7 +553,7 @@ public:
|
||||||
Play = 4
|
Play = 4
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit inline PDFActionRendition(std::optional<PDFRendition>&& rendition, PDFObjectReference annotation, Operation operation, QString javascript) :
|
explicit inline PDFActionRendition(std::optional<PDFRendition> rendition, PDFObjectReference annotation, Operation operation, QString javascript) :
|
||||||
m_rendition(qMove(rendition)),
|
m_rendition(qMove(rendition)),
|
||||||
m_annotation(annotation),
|
m_annotation(annotation),
|
||||||
m_operation(operation),
|
m_operation(operation),
|
||||||
|
@ -521,6 +569,8 @@ public:
|
||||||
Operation getOperation() const { return m_operation; }
|
Operation getOperation() const { return m_operation; }
|
||||||
const QString& getJavaScript() const { return m_javascript; }
|
const QString& getJavaScript() const { return m_javascript; }
|
||||||
|
|
||||||
|
virtual PDFActionPtr clone() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::optional<PDFRendition> m_rendition;
|
std::optional<PDFRendition> m_rendition;
|
||||||
PDFObjectReference m_annotation;
|
PDFObjectReference m_annotation;
|
||||||
|
@ -531,7 +581,7 @@ private:
|
||||||
class PDFActionTransition : public PDFAction
|
class PDFActionTransition : public PDFAction
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit inline PDFActionTransition(PDFPageTransition&& transition) :
|
explicit inline PDFActionTransition(PDFPageTransition transition) :
|
||||||
m_transition(qMove(transition))
|
m_transition(qMove(transition))
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -541,6 +591,8 @@ public:
|
||||||
|
|
||||||
const PDFPageTransition& getTransition() const { return m_transition; }
|
const PDFPageTransition& getTransition() const { return m_transition; }
|
||||||
|
|
||||||
|
virtual PDFActionPtr clone() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PDFPageTransition m_transition;
|
PDFPageTransition m_transition;
|
||||||
};
|
};
|
||||||
|
@ -560,6 +612,8 @@ public:
|
||||||
const PDFObject& getAnnotation() const { return m_annotation; }
|
const PDFObject& getAnnotation() const { return m_annotation; }
|
||||||
const PDFObject& getView() const { return m_view; }
|
const PDFObject& getView() const { return m_view; }
|
||||||
|
|
||||||
|
virtual PDFActionPtr clone() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PDFObject m_annotation;
|
PDFObject m_annotation;
|
||||||
PDFObject m_view;
|
PDFObject m_view;
|
||||||
|
@ -578,6 +632,8 @@ public:
|
||||||
|
|
||||||
const QString& getJavaScript() const { return m_javaScript; }
|
const QString& getJavaScript() const { return m_javaScript; }
|
||||||
|
|
||||||
|
virtual PDFActionPtr clone() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString m_javaScript;
|
QString m_javaScript;
|
||||||
};
|
};
|
||||||
|
@ -604,6 +660,8 @@ public:
|
||||||
QString getCommand() const { return m_command; }
|
QString getCommand() const { return m_command; }
|
||||||
PDFObject getArguments() const { return m_arguments; }
|
PDFObject getArguments() const { return m_arguments; }
|
||||||
|
|
||||||
|
virtual PDFActionPtr clone() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PDFObjectReference m_richMediaAnnotation;
|
PDFObjectReference m_richMediaAnnotation;
|
||||||
PDFObjectReference m_richMediaInstance;
|
PDFObjectReference m_richMediaInstance;
|
||||||
|
@ -689,6 +747,8 @@ public:
|
||||||
const QByteArray& getCharset() const { return m_charset; }
|
const QByteArray& getCharset() const { return m_charset; }
|
||||||
SubmitFlags getFlags() const { return m_flags; }
|
SubmitFlags getFlags() const { return m_flags; }
|
||||||
|
|
||||||
|
virtual PDFActionPtr clone() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PDFFileSpecification m_url;
|
PDFFileSpecification m_url;
|
||||||
QByteArray m_charset;
|
QByteArray m_charset;
|
||||||
|
@ -717,6 +777,8 @@ public:
|
||||||
|
|
||||||
ResetFlags getFlags() const { return m_flags; }
|
ResetFlags getFlags() const { return m_flags; }
|
||||||
|
|
||||||
|
virtual PDFActionPtr clone() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ResetFlags m_flags = None;
|
ResetFlags m_flags = None;
|
||||||
};
|
};
|
||||||
|
@ -735,6 +797,8 @@ public:
|
||||||
|
|
||||||
const PDFFileSpecification& getFile() const { return m_file; }
|
const PDFFileSpecification& getFile() const { return m_file; }
|
||||||
|
|
||||||
|
virtual PDFActionPtr clone() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PDFFileSpecification m_file;
|
PDFFileSpecification m_file;
|
||||||
};
|
};
|
||||||
|
|
|
@ -35,6 +35,13 @@ PDFTreeItem::~PDFTreeItem()
|
||||||
qDeleteAll(m_children);
|
qDeleteAll(m_children);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PDFTreeItem* PDFTreeItem::takeChild(int index)
|
||||||
|
{
|
||||||
|
PDFTreeItem* item = m_children.at(index);
|
||||||
|
m_children.erase(m_children.begin() + index);
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
PDFTreeItemModel::PDFTreeItemModel(QObject* parent) :
|
PDFTreeItemModel::PDFTreeItemModel(QObject* parent) :
|
||||||
QAbstractItemModel(parent),
|
QAbstractItemModel(parent),
|
||||||
m_document(nullptr)
|
m_document(nullptr)
|
||||||
|
@ -368,6 +375,7 @@ QVariant PDFOutlineTreeItemModel::data(const QModelIndex& index, int role) const
|
||||||
switch (role)
|
switch (role)
|
||||||
{
|
{
|
||||||
case Qt::DisplayRole:
|
case Qt::DisplayRole:
|
||||||
|
case Qt::EditRole:
|
||||||
return outlineItem->getTitle();
|
return outlineItem->getTitle();
|
||||||
|
|
||||||
case Qt::ForegroundRole:
|
case Qt::ForegroundRole:
|
||||||
|
@ -409,6 +417,11 @@ void PDFOutlineTreeItemModel::update()
|
||||||
}
|
}
|
||||||
if (outlineRoot)
|
if (outlineRoot)
|
||||||
{
|
{
|
||||||
|
if (m_editable)
|
||||||
|
{
|
||||||
|
outlineRoot = outlineRoot->clone();
|
||||||
|
}
|
||||||
|
|
||||||
m_rootItem.reset(new PDFOutlineTreeItem(nullptr, qMove(outlineRoot)));
|
m_rootItem.reset(new PDFOutlineTreeItem(nullptr, qMove(outlineRoot)));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -425,13 +438,16 @@ Qt::ItemFlags PDFOutlineTreeItemModel::flags(const QModelIndex& index) const
|
||||||
|
|
||||||
if (!index.isValid())
|
if (!index.isValid())
|
||||||
{
|
{
|
||||||
|
if (m_editable)
|
||||||
|
{
|
||||||
|
flags = flags | Qt::ItemIsDropEnabled;
|
||||||
|
}
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
const PDFOutlineTreeItem* item = static_cast<const PDFOutlineTreeItem*>(index.internalPointer());
|
if (m_editable)
|
||||||
if (item->getChildCount() == 0)
|
|
||||||
{
|
{
|
||||||
flags = flags | Qt::ItemNeverHasChildren;
|
flags = flags | Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
return flags;
|
return flags;
|
||||||
|
@ -449,6 +465,259 @@ const PDFAction* PDFOutlineTreeItemModel::getAction(const QModelIndex& index) co
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const PDFOutlineItem* PDFOutlineTreeItemModel::getOutlineItem(const QModelIndex& index) const
|
||||||
|
{
|
||||||
|
if (index.isValid())
|
||||||
|
{
|
||||||
|
const PDFOutlineTreeItem* item = static_cast<const PDFOutlineTreeItem*>(index.internalPointer());
|
||||||
|
const PDFOutlineItem* outlineItem = item->getOutlineItem();
|
||||||
|
return outlineItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFOutlineItem* PDFOutlineTreeItemModel::getOutlineItem(const QModelIndex& index)
|
||||||
|
{
|
||||||
|
if (index.isValid())
|
||||||
|
{
|
||||||
|
PDFOutlineTreeItem* item = static_cast<PDFOutlineTreeItem*>(index.internalPointer());
|
||||||
|
PDFOutlineItem* outlineItem = item->getOutlineItem();
|
||||||
|
return outlineItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDFOutlineTreeItemModel::setFontBold(const QModelIndex& index, bool value)
|
||||||
|
{
|
||||||
|
if (PDFOutlineItem* outlineItem = getOutlineItem(index))
|
||||||
|
{
|
||||||
|
if (outlineItem->isFontBold() != value)
|
||||||
|
{
|
||||||
|
outlineItem->setFontBold(value);
|
||||||
|
Q_EMIT dataChanged(index, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDFOutlineTreeItemModel::setFontItalics(const QModelIndex& index, bool value)
|
||||||
|
{
|
||||||
|
if (PDFOutlineItem* outlineItem = getOutlineItem(index))
|
||||||
|
{
|
||||||
|
if (outlineItem->isFontItalics() != value)
|
||||||
|
{
|
||||||
|
outlineItem->setFontItalics(value);
|
||||||
|
Q_EMIT dataChanged(index, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDFOutlineTreeItemModel::setDestination(const QModelIndex& index, const PDFDestination& destination)
|
||||||
|
{
|
||||||
|
if (PDFOutlineItem* outlineItem = getOutlineItem(index))
|
||||||
|
{
|
||||||
|
outlineItem->setAction(PDFActionPtr(new PDFActionGoTo(destination, PDFDestination())));
|
||||||
|
Q_EMIT dataChanged(index, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PDFOutlineTreeItemModel::setData(const QModelIndex& index, const QVariant& value, int role)
|
||||||
|
{
|
||||||
|
if (!m_editable || !index.isValid() || role != Qt::EditRole)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFOutlineTreeItem* item = static_cast<PDFOutlineTreeItem*>(index.internalPointer());
|
||||||
|
PDFOutlineItem* outlineItem = item->getOutlineItem();
|
||||||
|
if (outlineItem->getTitle() != value.toString())
|
||||||
|
{
|
||||||
|
outlineItem->setTitle(value.toString());
|
||||||
|
Q_EMIT dataChanged(index, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Qt::DropActions PDFOutlineTreeItemModel::supportedDropActions() const
|
||||||
|
{
|
||||||
|
if (!m_editable)
|
||||||
|
{
|
||||||
|
return Qt::IgnoreAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Qt::CopyAction | Qt::MoveAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
Qt::DropActions PDFOutlineTreeItemModel::supportedDragActions() const
|
||||||
|
{
|
||||||
|
if (!m_editable)
|
||||||
|
{
|
||||||
|
return Qt::IgnoreAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Qt::CopyAction | Qt::MoveAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList PDFOutlineTreeItemModel::mimeTypes() const
|
||||||
|
{
|
||||||
|
return QStringList() << "application/PDF4QT_PDFOutlineTreeItemModel";
|
||||||
|
}
|
||||||
|
|
||||||
|
QMimeData* PDFOutlineTreeItemModel::mimeData(const QModelIndexList& indexes) const
|
||||||
|
{
|
||||||
|
QMimeData* mimeData = new QMimeData();
|
||||||
|
|
||||||
|
if (indexes.size() == 1)
|
||||||
|
{
|
||||||
|
QByteArray ba;
|
||||||
|
|
||||||
|
{
|
||||||
|
QDataStream stream(&ba, QDataStream::WriteOnly);
|
||||||
|
stream << indexes.front().internalId();
|
||||||
|
}
|
||||||
|
|
||||||
|
mimeData->setData(mimeTypes().front(), ba);
|
||||||
|
}
|
||||||
|
|
||||||
|
return mimeData;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PDFOutlineTreeItemModel::canDropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(row);
|
||||||
|
Q_UNUSED(column);
|
||||||
|
Q_UNUSED(parent);
|
||||||
|
|
||||||
|
return action == Qt::MoveAction && data->hasFormat(mimeTypes().front());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PDFOutlineTreeItemModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent)
|
||||||
|
{
|
||||||
|
if (!data || action != Qt::MoveAction)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray pointerData = data->data(mimeTypes().front());
|
||||||
|
QDataStream stream(pointerData);
|
||||||
|
quintptr pointer = 0;
|
||||||
|
stream >> pointer;
|
||||||
|
|
||||||
|
PDFOutlineTreeItem* item = reinterpret_cast<PDFOutlineTreeItem*>(pointer);
|
||||||
|
QModelIndex sourceIndex = createIndex(item->getRow(), column, item);
|
||||||
|
return moveRow(sourceIndex.parent(), sourceIndex.row(), parent, row);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PDFOutlineTreeItemModel::insertRows(int row, int count, const QModelIndex& parent)
|
||||||
|
{
|
||||||
|
if (!m_editable || row < 0 || count <= 0 || row > rowCount(parent))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
beginInsertRows(parent, row, row + count - 1);
|
||||||
|
|
||||||
|
PDFOutlineTreeItem* item = parent.isValid() ? static_cast<PDFOutlineTreeItem*>(parent.internalPointer()) : static_cast<PDFOutlineTreeItem*>(m_rootItem.get());
|
||||||
|
while (count > 0)
|
||||||
|
{
|
||||||
|
QSharedPointer<PDFOutlineItem> outlineItem(new PDFOutlineItem());
|
||||||
|
outlineItem->setTitle(tr("Item %1").arg(row + 1));
|
||||||
|
PDFOutlineTreeItem* newTreeItem = new PDFOutlineTreeItem(item, qMove(outlineItem));
|
||||||
|
item->insertCreatedChild(row, newTreeItem);
|
||||||
|
|
||||||
|
++row;
|
||||||
|
--count;
|
||||||
|
}
|
||||||
|
|
||||||
|
endInsertRows();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PDFOutlineTreeItemModel::removeRows(int row, int count, const QModelIndex& parent)
|
||||||
|
{
|
||||||
|
if (!m_editable || count <= 0 || row < 0 || row + count > rowCount(parent))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
beginRemoveRows(parent, row, row + count - 1);
|
||||||
|
|
||||||
|
PDFOutlineTreeItem* item = parent.isValid() ? static_cast<PDFOutlineTreeItem*>(parent.internalPointer()) : static_cast<PDFOutlineTreeItem*>(m_rootItem.get());
|
||||||
|
while (count > 0)
|
||||||
|
{
|
||||||
|
delete item->takeChild(row);
|
||||||
|
--count;
|
||||||
|
}
|
||||||
|
|
||||||
|
endRemoveRows();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PDFOutlineTreeItemModel::moveRows(const QModelIndex& sourceParent, int sourceRow, int count, const QModelIndex& destinationParent, int destinationChild)
|
||||||
|
{
|
||||||
|
if (sourceRow < 0 || count <= 0 || (sourceParent == destinationParent && (sourceRow == destinationChild || sourceRow + count <= destinationChild)))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFOutlineTreeItem* sourceNode = nullptr;
|
||||||
|
PDFOutlineTreeItem* destNode = nullptr;
|
||||||
|
|
||||||
|
if (sourceParent.isValid())
|
||||||
|
{
|
||||||
|
sourceNode = static_cast<PDFOutlineTreeItem*>(sourceParent.internalPointer());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sourceNode = static_cast<PDFOutlineTreeItem*>(m_rootItem.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (destinationParent.isValid())
|
||||||
|
{
|
||||||
|
destNode = static_cast<PDFOutlineTreeItem*>(destinationParent.internalPointer());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
destNode = static_cast<PDFOutlineTreeItem*>(m_rootItem.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sourceRow + count > sourceNode->getChildCount())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (destinationChild < 0)
|
||||||
|
{
|
||||||
|
destinationChild = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Signalizace začátku přesunu řádků
|
||||||
|
if (!beginMoveRows(sourceParent, sourceRow, sourceRow + count - 1, destinationParent, destinationChild))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<PDFOutlineTreeItem*> nodesToMove;
|
||||||
|
for (int i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
nodesToMove.append(static_cast<PDFOutlineTreeItem*>(sourceNode->takeChild(sourceRow)));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (PDFOutlineTreeItem* node : nodesToMove)
|
||||||
|
{
|
||||||
|
destNode->insertCreatedChild(destinationChild++, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Signalizace konce přesunu řádků
|
||||||
|
endMoveRows();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
int PDFAttachmentsTreeItemModel::columnCount(const QModelIndex& parent) const
|
int PDFAttachmentsTreeItemModel::columnCount(const QModelIndex& parent) const
|
||||||
{
|
{
|
||||||
Q_UNUSED(parent);
|
Q_UNUSED(parent);
|
||||||
|
|
|
@ -36,6 +36,7 @@ class PDFModifiedDocument;
|
||||||
class PDFFileSpecification;
|
class PDFFileSpecification;
|
||||||
class PDFOptionalContentActivity;
|
class PDFOptionalContentActivity;
|
||||||
class PDFDrawWidgetProxy;
|
class PDFDrawWidgetProxy;
|
||||||
|
class PDFDestination;
|
||||||
|
|
||||||
/// Represents tree item in the GUI tree
|
/// Represents tree item in the GUI tree
|
||||||
class PDF4QTLIBSHARED_EXPORT PDFTreeItem
|
class PDF4QTLIBSHARED_EXPORT PDFTreeItem
|
||||||
|
@ -53,6 +54,20 @@ public:
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T, typename... Arguments>
|
||||||
|
inline T* insertChild(int position, Arguments&&... arguments)
|
||||||
|
{
|
||||||
|
T* item = new T(this, std::forward(arguments)...);
|
||||||
|
m_children.insert(std::next(m_children.begin(), position), item);
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
void insertCreatedChild(int position, PDFTreeItem* item)
|
||||||
|
{
|
||||||
|
item->m_parent = this;
|
||||||
|
m_children.insert(std::next(m_children.begin(), position), item);
|
||||||
|
}
|
||||||
|
|
||||||
void addCreatedChild(PDFTreeItem* item)
|
void addCreatedChild(PDFTreeItem* item)
|
||||||
{
|
{
|
||||||
item->m_parent = this;
|
item->m_parent = this;
|
||||||
|
@ -64,6 +79,7 @@ public:
|
||||||
const PDFTreeItem* getChild(int index) const { return m_children.at(index); }
|
const PDFTreeItem* getChild(int index) const { return m_children.at(index); }
|
||||||
PDFTreeItem* getChild(int index) { return m_children.at(index); }
|
PDFTreeItem* getChild(int index) { return m_children.at(index); }
|
||||||
const PDFTreeItem* getParent() const { return m_parent; }
|
const PDFTreeItem* getParent() const { return m_parent; }
|
||||||
|
PDFTreeItem* takeChild(int index);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PDFTreeItem* m_parent = nullptr;
|
PDFTreeItem* m_parent = nullptr;
|
||||||
|
@ -145,6 +161,7 @@ public:
|
||||||
explicit PDFOutlineTreeItem(PDFOutlineTreeItem* parent, QSharedPointer<PDFOutlineItem> outlineItem);
|
explicit PDFOutlineTreeItem(PDFOutlineTreeItem* parent, QSharedPointer<PDFOutlineItem> outlineItem);
|
||||||
|
|
||||||
const PDFOutlineItem* getOutlineItem() const { return m_outlineItem.data(); }
|
const PDFOutlineItem* getOutlineItem() const { return m_outlineItem.data(); }
|
||||||
|
PDFOutlineItem* getOutlineItem() { return m_outlineItem.data(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QSharedPointer<PDFOutlineItem> m_outlineItem;
|
QSharedPointer<PDFOutlineItem> m_outlineItem;
|
||||||
|
@ -154,9 +171,10 @@ class PDF4QTLIBSHARED_EXPORT PDFOutlineTreeItemModel : public PDFTreeItemModel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
PDFOutlineTreeItemModel(QIcon icon, QObject* parent) :
|
PDFOutlineTreeItemModel(QIcon icon, bool editable, QObject* parent) :
|
||||||
PDFTreeItemModel(parent),
|
PDFTreeItemModel(parent),
|
||||||
m_icon(qMove(icon))
|
m_icon(qMove(icon)),
|
||||||
|
m_editable(editable)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -165,14 +183,37 @@ public:
|
||||||
virtual QVariant data(const QModelIndex& index, int role) const override;
|
virtual QVariant data(const QModelIndex& index, int role) const override;
|
||||||
virtual void update() override;
|
virtual void update() override;
|
||||||
virtual Qt::ItemFlags flags(const QModelIndex& index) const override;
|
virtual Qt::ItemFlags flags(const QModelIndex& index) const override;
|
||||||
|
virtual bool setData(const QModelIndex& index, const QVariant& value, int role) override;
|
||||||
|
virtual Qt::DropActions supportedDropActions() const override;
|
||||||
|
virtual Qt::DropActions supportedDragActions() const override;
|
||||||
|
virtual bool insertRows(int row, int count, const QModelIndex& parent) override;
|
||||||
|
virtual bool removeRows(int row, int count, const QModelIndex& parent) override;
|
||||||
|
virtual bool moveRows(const QModelIndex& sourceParent, int sourceRow, int count, const QModelIndex& destinationParent, int destinationChild) override;
|
||||||
|
virtual QStringList mimeTypes() const override;
|
||||||
|
virtual QMimeData* mimeData(const QModelIndexList& indexes) const override;
|
||||||
|
virtual bool canDropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) const override;
|
||||||
|
virtual bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) override;
|
||||||
|
|
||||||
/// Returns action assigned to the index. If index is invalid, or
|
/// Returns action assigned to the index. If index is invalid, or
|
||||||
/// points to the invalid item, nullptr is returned.
|
/// points to the invalid item, nullptr is returned.
|
||||||
/// \param index Index of the outline item
|
/// \param index Index of the outline item
|
||||||
const PDFAction* getAction(const QModelIndex& index) const;
|
const PDFAction* getAction(const QModelIndex& index) const;
|
||||||
|
|
||||||
|
/// Returns the outline item for the given index, or nullptr
|
||||||
|
/// if no outline item is assigned to that index.
|
||||||
|
const PDFOutlineItem* getOutlineItem(const QModelIndex& index) const;
|
||||||
|
|
||||||
|
/// Returns the outline item for the given index, or nullptr
|
||||||
|
/// if no outline item is assigned to that index.
|
||||||
|
PDFOutlineItem* getOutlineItem(const QModelIndex& index);
|
||||||
|
|
||||||
|
void setFontBold(const QModelIndex& index, bool value);
|
||||||
|
void setFontItalics(const QModelIndex& index, bool value);
|
||||||
|
void setDestination(const QModelIndex& index, const PDFDestination& destination);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QIcon m_icon;
|
QIcon m_icon;
|
||||||
|
bool m_editable;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PDF4QTLIBSHARED_EXPORT PDFSelectableOutlineTreeItemModel : public PDFOutlineTreeItemModel
|
class PDF4QTLIBSHARED_EXPORT PDFSelectableOutlineTreeItemModel : public PDFOutlineTreeItemModel
|
||||||
|
@ -184,7 +225,7 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PDFSelectableOutlineTreeItemModel(QIcon icon, QObject* parent) :
|
PDFSelectableOutlineTreeItemModel(QIcon icon, QObject* parent) :
|
||||||
BaseClass(qMove(icon), parent)
|
BaseClass(qMove(icon), false, parent)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -156,6 +156,29 @@ void PDFOutlineItem::apply(const std::function<void (PDFOutlineItem*)>& functor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QSharedPointer<PDFOutlineItem> PDFOutlineItem::clone() const
|
||||||
|
{
|
||||||
|
QSharedPointer<PDFOutlineItem> result(new PDFOutlineItem());
|
||||||
|
|
||||||
|
result->setTitle(getTitle());
|
||||||
|
result->setTextColor(getTextColor());
|
||||||
|
result->setStructureElement(getStructureElement());
|
||||||
|
result->setFontItalics(isFontItalics());
|
||||||
|
result->setFontBold(isFontBold());
|
||||||
|
|
||||||
|
if (auto action = getAction())
|
||||||
|
{
|
||||||
|
result->setAction(action->clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < getChildCount(); ++i)
|
||||||
|
{
|
||||||
|
result->addChild(getChild(i)->clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
bool PDFOutlineItem::isFontBold() const
|
bool PDFOutlineItem::isFontBold() const
|
||||||
{
|
{
|
||||||
return m_fontBold;
|
return m_fontBold;
|
||||||
|
|
|
@ -65,6 +65,8 @@ public:
|
||||||
|
|
||||||
void apply(const std::function<void(PDFOutlineItem*)>& functor);
|
void apply(const std::function<void(PDFOutlineItem*)>& functor);
|
||||||
|
|
||||||
|
QSharedPointer<PDFOutlineItem> clone() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void parseImpl(const PDFObjectStorage* storage,
|
static void parseImpl(const PDFObjectStorage* storage,
|
||||||
PDFOutlineItem* parent,
|
PDFOutlineItem* parent,
|
||||||
|
|
|
@ -23,6 +23,8 @@
|
||||||
#include "pdfwidgetutils.h"
|
#include "pdfwidgetutils.h"
|
||||||
#include "pdftexttospeech.h"
|
#include "pdftexttospeech.h"
|
||||||
#include "pdfdbgheap.h"
|
#include "pdfdbgheap.h"
|
||||||
|
#include "pdfdrawwidget.h"
|
||||||
|
#include "pdfwidgettool.h"
|
||||||
|
|
||||||
#include "pdfdocument.h"
|
#include "pdfdocument.h"
|
||||||
#include "pdfitemmodels.h"
|
#include "pdfitemmodels.h"
|
||||||
|
@ -53,6 +55,7 @@ PDFSidebarWidget::PDFSidebarWidget(pdf::PDFDrawWidgetProxy* proxy,
|
||||||
PDFTextToSpeech* textToSpeech,
|
PDFTextToSpeech* textToSpeech,
|
||||||
pdf::PDFCertificateStore* certificateStore,
|
pdf::PDFCertificateStore* certificateStore,
|
||||||
PDFViewerSettings* settings,
|
PDFViewerSettings* settings,
|
||||||
|
bool editableOutline,
|
||||||
QWidget* parent) :
|
QWidget* parent) :
|
||||||
QWidget(parent),
|
QWidget(parent),
|
||||||
ui(new Ui::PDFSidebarWidget),
|
ui(new Ui::PDFSidebarWidget),
|
||||||
|
@ -73,9 +76,20 @@ PDFSidebarWidget::PDFSidebarWidget(pdf::PDFDrawWidgetProxy* proxy,
|
||||||
|
|
||||||
// Outline
|
// Outline
|
||||||
QIcon bookmarkIcon(":/resources/bookmark.svg");
|
QIcon bookmarkIcon(":/resources/bookmark.svg");
|
||||||
m_outlineTreeModel = new pdf::PDFOutlineTreeItemModel(qMove(bookmarkIcon), this);
|
m_outlineTreeModel = new pdf::PDFOutlineTreeItemModel(qMove(bookmarkIcon), editableOutline, this);
|
||||||
ui->bookmarksTreeView->setModel(m_outlineTreeModel);
|
ui->bookmarksTreeView->setModel(m_outlineTreeModel);
|
||||||
ui->bookmarksTreeView->header()->hide();
|
ui->bookmarksTreeView->header()->hide();
|
||||||
|
|
||||||
|
if (editableOutline)
|
||||||
|
{
|
||||||
|
ui->bookmarksTreeView->setDragEnabled(true);
|
||||||
|
ui->bookmarksTreeView->setAcceptDrops(true);
|
||||||
|
ui->bookmarksTreeView->setDropIndicatorShown(true);
|
||||||
|
ui->bookmarksTreeView->setDragDropMode(QAbstractItemView::InternalMove);
|
||||||
|
ui->bookmarksTreeView->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
|
connect(ui->bookmarksTreeView, &QTreeView::customContextMenuRequested, this, &PDFSidebarWidget::onBookmarksTreeViewContextMenuRequested);
|
||||||
|
}
|
||||||
|
|
||||||
connect(ui->bookmarksTreeView, &QTreeView::clicked, this, &PDFSidebarWidget::onOutlineItemClicked);
|
connect(ui->bookmarksTreeView, &QTreeView::clicked, this, &PDFSidebarWidget::onOutlineItemClicked);
|
||||||
|
|
||||||
// Thumbnails
|
// Thumbnails
|
||||||
|
@ -735,6 +749,119 @@ void PDFSidebarWidget::onSignatureCustomContextMenuRequested(const QPoint& pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PDFSidebarWidget::onBookmarksTreeViewContextMenuRequested(const QPoint& pos)
|
||||||
|
{
|
||||||
|
QMenu contextMenu;
|
||||||
|
|
||||||
|
QModelIndex index = ui->bookmarksTreeView->indexAt(pos);
|
||||||
|
|
||||||
|
auto onFollow = [this, index]()
|
||||||
|
{
|
||||||
|
onOutlineItemClicked(index);
|
||||||
|
};
|
||||||
|
|
||||||
|
auto onInsert = [this, index]()
|
||||||
|
{
|
||||||
|
if (index.isValid())
|
||||||
|
{
|
||||||
|
ui->bookmarksTreeView->model()->insertRow(index.row() + 1, index.parent());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ui->bookmarksTreeView->model()->insertRow(ui->bookmarksTreeView->model()->rowCount());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
auto onDelete = [this, index]()
|
||||||
|
{
|
||||||
|
ui->bookmarksTreeView->model()->removeRow(index.row(), index.parent());
|
||||||
|
};
|
||||||
|
|
||||||
|
auto onRename = [this, index]()
|
||||||
|
{
|
||||||
|
ui->bookmarksTreeView->edit(index);
|
||||||
|
};
|
||||||
|
|
||||||
|
QAction* followAction = contextMenu.addAction(tr("Follow"), onFollow);
|
||||||
|
followAction->setEnabled(index.isValid());
|
||||||
|
contextMenu.addSeparator();
|
||||||
|
|
||||||
|
QAction* deleteAction = contextMenu.addAction(tr("Delete"), onDelete);
|
||||||
|
QAction* insertAction = contextMenu.addAction(tr("Insert"), this, onInsert);
|
||||||
|
QAction* renameAction = contextMenu.addAction(tr("Rename"), this, onRename);
|
||||||
|
|
||||||
|
deleteAction->setEnabled(index.isValid());
|
||||||
|
insertAction->setEnabled(true);
|
||||||
|
renameAction->setEnabled(index.isValid());
|
||||||
|
|
||||||
|
contextMenu.addSeparator();
|
||||||
|
|
||||||
|
const pdf::PDFOutlineItem* outlineItem = m_outlineTreeModel->getOutlineItem(index);
|
||||||
|
const bool isFontBold = outlineItem && outlineItem->isFontBold();
|
||||||
|
const bool isFontItalics = outlineItem && outlineItem->isFontItalics();
|
||||||
|
|
||||||
|
auto onFontBold = [this, index, isFontBold]()
|
||||||
|
{
|
||||||
|
m_outlineTreeModel->setFontBold(index, !isFontBold);
|
||||||
|
};
|
||||||
|
|
||||||
|
auto onFontItalic = [this, index, isFontItalics]()
|
||||||
|
{
|
||||||
|
m_outlineTreeModel->setFontItalics(index, !isFontItalics);
|
||||||
|
};
|
||||||
|
|
||||||
|
QAction* fontBoldAction = contextMenu.addAction(tr("Font Bold"), onFontBold);
|
||||||
|
QAction* fontItalicAction = contextMenu.addAction(tr("Font Italic"), onFontItalic);
|
||||||
|
fontBoldAction->setCheckable(true);
|
||||||
|
fontItalicAction->setCheckable(true);
|
||||||
|
fontBoldAction->setChecked(isFontBold);
|
||||||
|
fontItalicAction->setChecked(isFontItalics);
|
||||||
|
fontBoldAction->setEnabled(index.isValid());
|
||||||
|
fontItalicAction->setEnabled(index.isValid());
|
||||||
|
|
||||||
|
QMenu* submenu = new QMenu(tr("Set Target"), &contextMenu);
|
||||||
|
QAction* targetAction = contextMenu.addMenu(submenu);
|
||||||
|
targetAction->setEnabled(index.isValid());
|
||||||
|
|
||||||
|
auto createOnSetTarget = [this, index](pdf::DestinationType destinationType)
|
||||||
|
{
|
||||||
|
auto onSetTarget = [this, index, destinationType]()
|
||||||
|
{
|
||||||
|
pdf::PDFToolManager* toolManager = m_proxy->getWidget()->getToolManager();
|
||||||
|
|
||||||
|
auto pickRectangle = [this, index, destinationType](pdf::PDFInteger pageIndex, QRectF rect)
|
||||||
|
{
|
||||||
|
pdf::PDFDestination destination;
|
||||||
|
destination.setDestinationType(destinationType);
|
||||||
|
destination.setPageIndex(pageIndex);
|
||||||
|
destination.setPageReference(m_document->getCatalog()->getPage(pageIndex)->getPageReference());
|
||||||
|
destination.setLeft(rect.left());
|
||||||
|
destination.setRight(rect.right());
|
||||||
|
destination.setTop(rect.bottom());
|
||||||
|
destination.setBottom(rect.top());
|
||||||
|
destination.setZoom(m_proxy->getZoom());
|
||||||
|
m_outlineTreeModel->setDestination(index, destination);
|
||||||
|
};
|
||||||
|
|
||||||
|
toolManager->pickRectangle(pickRectangle);
|
||||||
|
};
|
||||||
|
|
||||||
|
return onSetTarget;
|
||||||
|
};
|
||||||
|
|
||||||
|
submenu->addAction(tr("Named Destination"));
|
||||||
|
submenu->addAction(tr("Fit Page"), createOnSetTarget(pdf::DestinationType::Fit));
|
||||||
|
submenu->addAction(tr("Fit Page Horizontally"), createOnSetTarget(pdf::DestinationType::FitH));
|
||||||
|
submenu->addAction(tr("Fit Page Vertically"), createOnSetTarget(pdf::DestinationType::FitV));
|
||||||
|
submenu->addAction(tr("Fit Rectangle"), createOnSetTarget(pdf::DestinationType::FitR));
|
||||||
|
submenu->addAction(tr("Fit Bounding Box"), createOnSetTarget(pdf::DestinationType::FitB));
|
||||||
|
submenu->addAction(tr("Fit Bounding Box Horizontally"), createOnSetTarget(pdf::DestinationType::FitBH));
|
||||||
|
submenu->addAction(tr("Fit Bounding Box Vertically"), createOnSetTarget(pdf::DestinationType::FitBV));
|
||||||
|
submenu->addAction(tr("XYZ"), createOnSetTarget(pdf::DestinationType::XYZ));
|
||||||
|
|
||||||
|
contextMenu.exec(ui->bookmarksTreeView->mapToGlobal(pos));
|
||||||
|
}
|
||||||
|
|
||||||
void PDFSidebarWidget::paintEvent(QPaintEvent* event)
|
void PDFSidebarWidget::paintEvent(QPaintEvent* event)
|
||||||
{
|
{
|
||||||
Q_UNUSED(event);
|
Q_UNUSED(event);
|
||||||
|
|
|
@ -62,6 +62,7 @@ public:
|
||||||
PDFTextToSpeech* textToSpeech,
|
PDFTextToSpeech* textToSpeech,
|
||||||
pdf::PDFCertificateStore* certificateStore,
|
pdf::PDFCertificateStore* certificateStore,
|
||||||
PDFViewerSettings* settings,
|
PDFViewerSettings* settings,
|
||||||
|
bool editableOutline,
|
||||||
QWidget* parent);
|
QWidget* parent);
|
||||||
virtual ~PDFSidebarWidget() override;
|
virtual ~PDFSidebarWidget() override;
|
||||||
|
|
||||||
|
@ -111,6 +112,7 @@ private:
|
||||||
void onAttachmentCustomContextMenuRequested(const QPoint& pos);
|
void onAttachmentCustomContextMenuRequested(const QPoint& pos);
|
||||||
void onThumbnailClicked(const QModelIndex& index);
|
void onThumbnailClicked(const QModelIndex& index);
|
||||||
void onSignatureCustomContextMenuRequested(const QPoint &pos);
|
void onSignatureCustomContextMenuRequested(const QPoint &pos);
|
||||||
|
void onBookmarksTreeViewContextMenuRequested(const QPoint &pos);
|
||||||
|
|
||||||
struct PageInfo
|
struct PageInfo
|
||||||
{
|
{
|
||||||
|
|
|
@ -253,7 +253,7 @@ PDFViewerMainWindow::PDFViewerMainWindow(QWidget* parent) :
|
||||||
setCentralWidget(m_programController->getPdfWidget());
|
setCentralWidget(m_programController->getPdfWidget());
|
||||||
setFocusProxy(m_programController->getPdfWidget());
|
setFocusProxy(m_programController->getPdfWidget());
|
||||||
|
|
||||||
m_sidebarWidget = new PDFSidebarWidget(m_programController->getPdfWidget()->getDrawWidgetProxy(), m_programController->getTextToSpeech(), m_programController->getCertificateStore(), m_programController->getSettings(), this);
|
m_sidebarWidget = new PDFSidebarWidget(m_programController->getPdfWidget()->getDrawWidgetProxy(), m_programController->getTextToSpeech(), m_programController->getCertificateStore(), m_programController->getSettings(), true, this);
|
||||||
m_sidebarDockWidget = new QDockWidget(tr("Sidebar"), this);
|
m_sidebarDockWidget = new QDockWidget(tr("Sidebar"), this);
|
||||||
m_sidebarDockWidget->setObjectName("SidebarDockWidget");
|
m_sidebarDockWidget->setObjectName("SidebarDockWidget");
|
||||||
m_sidebarDockWidget->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
|
m_sidebarDockWidget->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
|
||||||
|
|
|
@ -188,7 +188,7 @@ PDFViewerMainWindowLite::PDFViewerMainWindowLite(QWidget* parent) :
|
||||||
setCentralWidget(m_programController->getPdfWidget());
|
setCentralWidget(m_programController->getPdfWidget());
|
||||||
setFocusProxy(m_programController->getPdfWidget());
|
setFocusProxy(m_programController->getPdfWidget());
|
||||||
|
|
||||||
m_sidebarWidget = new PDFSidebarWidget(m_programController->getPdfWidget()->getDrawWidgetProxy(), m_programController->getTextToSpeech(), m_programController->getCertificateStore(), m_programController->getSettings(), this);
|
m_sidebarWidget = new PDFSidebarWidget(m_programController->getPdfWidget()->getDrawWidgetProxy(), m_programController->getTextToSpeech(), m_programController->getCertificateStore(), m_programController->getSettings(), false, this);
|
||||||
m_sidebarDockWidget = new QDockWidget(tr("Sidebar"), this);
|
m_sidebarDockWidget = new QDockWidget(tr("Sidebar"), this);
|
||||||
m_sidebarDockWidget->setObjectName("SidebarDockWidget");
|
m_sidebarDockWidget->setObjectName("SidebarDockWidget");
|
||||||
m_sidebarDockWidget->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
|
m_sidebarDockWidget->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
|
||||||
|
|
Loading…
Reference in New Issue