mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-06-05 21:59:17 +02:00
Issue #76: Basic functionality of outline editing
This commit is contained in:
@ -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 result;
|
||||
@ -711,6 +722,16 @@ QString PDFActionURI::getURIString() const
|
||||
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)
|
||||
{
|
||||
m_destination = destination;
|
||||
@ -721,4 +742,153 @@ void PDFActionGoTo::setStructureDestination(const PDFDestination& structureDesti
|
||||
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
|
||||
|
@ -169,6 +169,12 @@ public:
|
||||
/// Returns list of actions to be executed
|
||||
std::vector<const PDFAction*> getActionList() const;
|
||||
|
||||
/// Clone action
|
||||
virtual PDFActionPtr clone() const = 0;
|
||||
|
||||
protected:
|
||||
void cloneActionList(const PDFAction* sourceAction);
|
||||
|
||||
private:
|
||||
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
|
||||
/// and structure destination are present, because if structure destination fails, then
|
||||
/// page destination can be used as fallback resolution.
|
||||
class PDFActionGoTo : public PDFAction
|
||||
class PDF4QTLIBSHARED_EXPORT PDFActionGoTo : public PDFAction
|
||||
{
|
||||
public:
|
||||
explicit inline PDFActionGoTo(PDFDestination destination, PDFDestination structureDestination) :
|
||||
@ -194,6 +200,8 @@ public:
|
||||
void setDestination(const PDFDestination& destination);
|
||||
void setStructureDestination(const PDFDestination& structureDestination);
|
||||
|
||||
virtual PDFActionPtr clone() const override;
|
||||
|
||||
private:
|
||||
PDFDestination m_destination;
|
||||
PDFDestination m_structureDestination;
|
||||
@ -218,6 +226,8 @@ public:
|
||||
const PDFFileSpecification& getFileSpecification() const { return m_fileSpecification; }
|
||||
bool isNewWindow() const { return m_newWindow; }
|
||||
|
||||
virtual PDFActionPtr clone() const override;
|
||||
|
||||
private:
|
||||
PDFDestination m_destination;
|
||||
PDFDestination m_structureDestination;
|
||||
@ -244,6 +254,8 @@ public:
|
||||
bool isNewWindow() const { return m_newWindow; }
|
||||
const PDFObject& getTarget() const { return m_target; }
|
||||
|
||||
virtual PDFActionPtr clone() const override;
|
||||
|
||||
private:
|
||||
PDFDestination m_destination;
|
||||
PDFFileSpecification m_fileSpecification;
|
||||
@ -262,6 +274,8 @@ public:
|
||||
|
||||
PDFObjectReference getDocumentPart() const { return m_documentPart; }
|
||||
|
||||
virtual PDFActionPtr clone() const override;
|
||||
|
||||
private:
|
||||
PDFObjectReference m_documentPart;
|
||||
};
|
||||
@ -293,6 +307,8 @@ public:
|
||||
const Win& getWinSpecification() const { return m_win; }
|
||||
bool isNewWindow() const { return m_newWindow; }
|
||||
|
||||
virtual PDFActionPtr clone() const override;
|
||||
|
||||
private:
|
||||
PDFFileSpecification m_fileSpecification;
|
||||
bool m_newWindow = false;
|
||||
@ -319,6 +335,8 @@ public:
|
||||
const Thread& getThread() const { return m_thread; }
|
||||
const Bead& getBead() const { return m_bead; }
|
||||
|
||||
virtual PDFActionPtr clone() const override;
|
||||
|
||||
private:
|
||||
PDFFileSpecification m_fileSpecification;
|
||||
Thread m_thread;
|
||||
@ -344,6 +362,11 @@ public:
|
||||
/// to PDF specification, URI is UTF-8 encoded string.
|
||||
QString getURIString() const;
|
||||
|
||||
virtual PDFActionPtr clone() const override;
|
||||
|
||||
void setURI(const QByteArray& newURI);
|
||||
void setIsMap(bool newIsMap);
|
||||
|
||||
private:
|
||||
QByteArray m_URI;
|
||||
bool m_isMap;
|
||||
@ -370,6 +393,8 @@ public:
|
||||
bool isRepeat() const { return m_isRepeat; }
|
||||
bool isMix() const { return m_isMix; }
|
||||
|
||||
virtual PDFActionPtr clone() const override;
|
||||
|
||||
private:
|
||||
PDFSound m_sound;
|
||||
PDFReal m_volume;
|
||||
@ -403,6 +428,8 @@ public:
|
||||
const QString& getTitle() const { return m_title; }
|
||||
Operation getOperation() const { return m_operation; }
|
||||
|
||||
virtual PDFActionPtr clone() const override;
|
||||
|
||||
private:
|
||||
PDFObjectReference m_annotation;
|
||||
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; }
|
||||
|
||||
const std::vector<PDFObjectReference>& getAnnotations() const { return m_annotations; }
|
||||
const std::vector<QString>& getFieldNames() const { return m_fieldNames; }
|
||||
bool isHide() const { return m_hide; }
|
||||
|
||||
virtual PDFActionPtr clone() const override;
|
||||
|
||||
private:
|
||||
std::vector<PDFObjectReference> m_annotations;
|
||||
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; }
|
||||
|
||||
NamedActionType getNamedActionType() const { return m_namedActionType; }
|
||||
const QByteArray& getCustomNamedAction() const { return m_customNamedAction; }
|
||||
|
||||
virtual PDFActionPtr clone() const override;
|
||||
|
||||
private:
|
||||
NamedActionType m_namedActionType;
|
||||
QByteArray m_customNamedAction;
|
||||
@ -475,7 +521,7 @@ public:
|
||||
using StateChangeItem = std::pair<SwitchType, PDFObjectReference>;
|
||||
using StateChangeItems = std::vector<StateChangeItem>;
|
||||
|
||||
explicit inline PDFActionSetOCGState(StateChangeItems&& stateChangeItems, bool isRadioButtonsPreserved) :
|
||||
explicit inline PDFActionSetOCGState(StateChangeItems stateChangeItems, bool isRadioButtonsPreserved) :
|
||||
m_items(qMove(stateChangeItems)),
|
||||
m_isRadioButtonsPreserved(isRadioButtonsPreserved)
|
||||
{
|
||||
@ -487,6 +533,8 @@ public:
|
||||
const StateChangeItems& getStateChangeItems() const { return m_items; }
|
||||
bool isRadioButtonsPreserved() const { return m_isRadioButtonsPreserved; }
|
||||
|
||||
virtual PDFActionPtr clone() const override;
|
||||
|
||||
private:
|
||||
StateChangeItems m_items;
|
||||
bool m_isRadioButtonsPreserved;
|
||||
@ -505,7 +553,7 @@ public:
|
||||
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_annotation(annotation),
|
||||
m_operation(operation),
|
||||
@ -521,6 +569,8 @@ public:
|
||||
Operation getOperation() const { return m_operation; }
|
||||
const QString& getJavaScript() const { return m_javascript; }
|
||||
|
||||
virtual PDFActionPtr clone() const override;
|
||||
|
||||
private:
|
||||
std::optional<PDFRendition> m_rendition;
|
||||
PDFObjectReference m_annotation;
|
||||
@ -531,7 +581,7 @@ private:
|
||||
class PDFActionTransition : public PDFAction
|
||||
{
|
||||
public:
|
||||
explicit inline PDFActionTransition(PDFPageTransition&& transition) :
|
||||
explicit inline PDFActionTransition(PDFPageTransition transition) :
|
||||
m_transition(qMove(transition))
|
||||
{
|
||||
|
||||
@ -541,6 +591,8 @@ public:
|
||||
|
||||
const PDFPageTransition& getTransition() const { return m_transition; }
|
||||
|
||||
virtual PDFActionPtr clone() const override;
|
||||
|
||||
private:
|
||||
PDFPageTransition m_transition;
|
||||
};
|
||||
@ -560,6 +612,8 @@ public:
|
||||
const PDFObject& getAnnotation() const { return m_annotation; }
|
||||
const PDFObject& getView() const { return m_view; }
|
||||
|
||||
virtual PDFActionPtr clone() const override;
|
||||
|
||||
private:
|
||||
PDFObject m_annotation;
|
||||
PDFObject m_view;
|
||||
@ -578,6 +632,8 @@ public:
|
||||
|
||||
const QString& getJavaScript() const { return m_javaScript; }
|
||||
|
||||
virtual PDFActionPtr clone() const override;
|
||||
|
||||
private:
|
||||
QString m_javaScript;
|
||||
};
|
||||
@ -604,6 +660,8 @@ public:
|
||||
QString getCommand() const { return m_command; }
|
||||
PDFObject getArguments() const { return m_arguments; }
|
||||
|
||||
virtual PDFActionPtr clone() const override;
|
||||
|
||||
private:
|
||||
PDFObjectReference m_richMediaAnnotation;
|
||||
PDFObjectReference m_richMediaInstance;
|
||||
@ -689,6 +747,8 @@ public:
|
||||
const QByteArray& getCharset() const { return m_charset; }
|
||||
SubmitFlags getFlags() const { return m_flags; }
|
||||
|
||||
virtual PDFActionPtr clone() const override;
|
||||
|
||||
private:
|
||||
PDFFileSpecification m_url;
|
||||
QByteArray m_charset;
|
||||
@ -717,6 +777,8 @@ public:
|
||||
|
||||
ResetFlags getFlags() const { return m_flags; }
|
||||
|
||||
virtual PDFActionPtr clone() const override;
|
||||
|
||||
private:
|
||||
ResetFlags m_flags = None;
|
||||
};
|
||||
@ -735,6 +797,8 @@ public:
|
||||
|
||||
const PDFFileSpecification& getFile() const { return m_file; }
|
||||
|
||||
virtual PDFActionPtr clone() const override;
|
||||
|
||||
private:
|
||||
PDFFileSpecification m_file;
|
||||
};
|
||||
|
@ -35,6 +35,13 @@ PDFTreeItem::~PDFTreeItem()
|
||||
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) :
|
||||
QAbstractItemModel(parent),
|
||||
m_document(nullptr)
|
||||
@ -368,6 +375,7 @@ QVariant PDFOutlineTreeItemModel::data(const QModelIndex& index, int role) const
|
||||
switch (role)
|
||||
{
|
||||
case Qt::DisplayRole:
|
||||
case Qt::EditRole:
|
||||
return outlineItem->getTitle();
|
||||
|
||||
case Qt::ForegroundRole:
|
||||
@ -409,6 +417,11 @@ void PDFOutlineTreeItemModel::update()
|
||||
}
|
||||
if (outlineRoot)
|
||||
{
|
||||
if (m_editable)
|
||||
{
|
||||
outlineRoot = outlineRoot->clone();
|
||||
}
|
||||
|
||||
m_rootItem.reset(new PDFOutlineTreeItem(nullptr, qMove(outlineRoot)));
|
||||
}
|
||||
else
|
||||
@ -425,13 +438,16 @@ Qt::ItemFlags PDFOutlineTreeItemModel::flags(const QModelIndex& index) const
|
||||
|
||||
if (!index.isValid())
|
||||
{
|
||||
if (m_editable)
|
||||
{
|
||||
flags = flags | Qt::ItemIsDropEnabled;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
const PDFOutlineTreeItem* item = static_cast<const PDFOutlineTreeItem*>(index.internalPointer());
|
||||
if (item->getChildCount() == 0)
|
||||
if (m_editable)
|
||||
{
|
||||
flags = flags | Qt::ItemNeverHasChildren;
|
||||
flags = flags | Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
|
||||
}
|
||||
|
||||
return flags;
|
||||
@ -449,6 +465,259 @@ const PDFAction* PDFOutlineTreeItemModel::getAction(const QModelIndex& index) co
|
||||
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
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
|
@ -36,6 +36,7 @@ class PDFModifiedDocument;
|
||||
class PDFFileSpecification;
|
||||
class PDFOptionalContentActivity;
|
||||
class PDFDrawWidgetProxy;
|
||||
class PDFDestination;
|
||||
|
||||
/// Represents tree item in the GUI tree
|
||||
class PDF4QTLIBSHARED_EXPORT PDFTreeItem
|
||||
@ -53,6 +54,20 @@ public:
|
||||
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)
|
||||
{
|
||||
item->m_parent = this;
|
||||
@ -64,6 +79,7 @@ public:
|
||||
const PDFTreeItem* getChild(int index) const { return m_children.at(index); }
|
||||
PDFTreeItem* getChild(int index) { return m_children.at(index); }
|
||||
const PDFTreeItem* getParent() const { return m_parent; }
|
||||
PDFTreeItem* takeChild(int index);
|
||||
|
||||
private:
|
||||
PDFTreeItem* m_parent = nullptr;
|
||||
@ -145,6 +161,7 @@ public:
|
||||
explicit PDFOutlineTreeItem(PDFOutlineTreeItem* parent, QSharedPointer<PDFOutlineItem> outlineItem);
|
||||
|
||||
const PDFOutlineItem* getOutlineItem() const { return m_outlineItem.data(); }
|
||||
PDFOutlineItem* getOutlineItem() { return m_outlineItem.data(); }
|
||||
|
||||
private:
|
||||
QSharedPointer<PDFOutlineItem> m_outlineItem;
|
||||
@ -154,9 +171,10 @@ class PDF4QTLIBSHARED_EXPORT PDFOutlineTreeItemModel : public PDFTreeItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
PDFOutlineTreeItemModel(QIcon icon, QObject* parent) :
|
||||
PDFOutlineTreeItemModel(QIcon icon, bool editable, QObject* 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 void update() 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
|
||||
/// points to the invalid item, nullptr is returned.
|
||||
/// \param index Index of the outline item
|
||||
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:
|
||||
QIcon m_icon;
|
||||
bool m_editable;
|
||||
};
|
||||
|
||||
class PDF4QTLIBSHARED_EXPORT PDFSelectableOutlineTreeItemModel : public PDFOutlineTreeItemModel
|
||||
@ -184,7 +225,7 @@ private:
|
||||
|
||||
public:
|
||||
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
|
||||
{
|
||||
return m_fontBold;
|
||||
|
@ -65,6 +65,8 @@ public:
|
||||
|
||||
void apply(const std::function<void(PDFOutlineItem*)>& functor);
|
||||
|
||||
QSharedPointer<PDFOutlineItem> clone() const;
|
||||
|
||||
private:
|
||||
static void parseImpl(const PDFObjectStorage* storage,
|
||||
PDFOutlineItem* parent,
|
||||
|
Reference in New Issue
Block a user