Copy link to clipboard
Copied
Hi,
I have a very simple test document with only one hyperlink.
I tried to to get IHyperlink via IHyperlinkSource but I got always NULL value for QueryHyperlinkSourceAt function.
textValue is correct so I think the dataModel and range.Start() parameter is right for QueryHyperlinkSourceAt function.
To get hyperlinks by IHyperlinktable is not solution for me because I would like to change the destination URL by en XML attribute "hyperlinkpattern" so I need to get IHyperlink via IIDXMLElement.
My code:
XMLReference xmlref = iter->first;
InterfacePtr<IIDXMLElement> elem(xmlref.Instantiate());
WideString elemName = elem->GetTagString();
WideString hyperlinkPattern = elem->GetAttributeValue(WideString("hyperlinkpattern"));
do {
XMLContentIterator iter(elem->begin());
InDesign::TextRange range = *iter;
if (!range.IsValid()) {
break;
}
InterfacePtr<ITextModel> textModel(range.QueryModel());
if (!textModel) {
break;
}
WideString textValue("");
TextIterator begin_(textModel, range.Start());
TextIterator end_(textModel, range.End());
for (TextIterator iterText = begin_; iterText != end_; iterText++) {
const UTF32TextChar characterCode = *iterText;
textValue.Append(characterCode);
}
InterfacePtr<IHyperlinkSource> hyperlinkSource(static_cast<IHyperlinkSource*>(Utils<IHyperlinkUtils>()->QueryHyperlinkSourceAt(textModel, range.Start())));
if (!hyperlinkSource) // <------------------ hyperlinkSource ALWAYS NULL
break;
InterfacePtr<IHyperlink> hyperlink(db, hyperlinkSource->GetOwningHyperlink(), IID_IHYPERLINK);
InterfacePtr<IHyperlinkDestination> hyperlinkDestination(db, hyperlink->GetDestinationUID(), IID_IHYPERLINKDESTINATION);
hyperlinkDestination->SetName(PMString("https://adobe.com")); // Redirect URL to adobe
} while (kFalse);
I appreciate any help.
Thx
Karoly
The following seems to work. Lot of work to find this(terse documentation to bless). This gives the idea, you can see if you get a more concise way of doing it. I have harcoded the query path for XMLElement, you can plug it with your code. One interesting thing is that even though the name is changed, it's not reflected on the hyperlinks panel even though querying it gives the chaged name.
InterfacePtr<IIDXMLElement> rootXMLElement(Utils<IXMLUtils>()->QueryRootElement(Utils<ILayoutUI
...
Copy link to clipboard
Copied
Hi Karoly,
Looking at your document I see that you have hyperlink on the textframe and not on the text inside it and hence the code fails. If you select the text inside the box and then apply hyperlink to it then hopefully it will work
-Manan
Copy link to clipboard
Copied
Hi Manan,
Thank you for your quick answer.
I will try it and let you know .
/Karoly
Copy link to clipboard
Copied
The following seems to work. Lot of work to find this(terse documentation to bless). This gives the idea, you can see if you get a more concise way of doing it. I have harcoded the query path for XMLElement, you can plug it with your code. One interesting thing is that even though the name is changed, it's not reflected on the hyperlinks panel even though querying it gives the chaged name.
InterfacePtr<IIDXMLElement> rootXMLElement(Utils<IXMLUtils>()->QueryRootElement(Utils<ILayoutUIUtils>()->GetFrontDocument()));
ASSERT(rootXMLElement);
if(!rootXMLElement)
break;
IIDXMLElement *elem = rootXMLElement->GetNthChild(0).Instantiate()->GetNthChild(0).Instantiate()->GetNthChild(0).Instantiate();
do {
XMLContentIterator iter(elem->begin());
InDesign::TextRange range = *iter;
if (!range.IsValid()) {
break;
}
InterfacePtr<ITextModel> textModel(range.QueryModel());
if (!textModel) {
break;
}
InterfacePtr<IFrameList> iFrameList(textModel->QueryFrameList());
if(!iFrameList)
break;
InterfacePtr<ITextFrameColumn> iTextFrameColumn(iFrameList->QueryNthFrame(0));
if(!iTextFrameColumn)
break;
InterfacePtr<IMultiColumnTextFrame> iMultiColumnTextFrame(iTextFrameColumn->QueryMultiColumnTextFrame());
if(!iMultiColumnTextFrame)
break;
InterfacePtr<IHierarchy> iHierarchy(iMultiColumnTextFrame, UseDefaultIID());
if(!iHierarchy)
break;
InterfacePtr<IHyperlinkPageItemData> iHyperlinkPageItemData(iHierarchy->QueryParent(), UseDefaultIID());
if(!iHyperlinkPageItemData)
break;
InterfacePtr<IHyperlinkSource> iHyperlinkSource(::GetDataBase(iHierarchy), iHyperlinkPageItemData->GetSource(), UseDefaultIID());
if(!iHyperlinkSource)
break;
InterfacePtr<IHyperlink> iHyperlink(::GetDataBase(iHierarchy), iHyperlinkSource->GetOwningHyperlink(), UseDefaultIID());
if(!iHyperlinkSource)
break;
InterfacePtr<IHyperlinkDestination> hyperlinkDestination(::GetDataBase(iHierarchy), iHyperlink->GetDestinationUID(), UseDefaultIID());
PMString name;
hyperlinkDestination->GetName(&name);
CAlert::InformationAlert(name);
hyperlinkDestination->SetName(PMString("https://adobe.com")); // Redirect URL to adobe
-Manan
Copy link to clipboard
Copied
Great job!
Thank you!
/Karoly
Copy link to clipboard
Copied
I'd guess the name will be changed if you use a kChangeHyperlinkCmdBoss for the setter.
It will notify selection attribute changes for suite IID_IHYPERLINKSUITE.
That command will also trigger preflight ...
Copy link to clipboard
Copied
Yeah I was getting an assert for direct change to database so the next action items was looking for the command. But I had already spent too much energy looking for the wherabouts of IHyperlinkPageItemData interface in the scheme of things. In the latest SDK's they have removed the information as to which boss class includes a particular interface. It's one hell of a task to look around.
-Manan
Copy link to clipboard
Copied
Hi Manan and Dirk,
To manipulate destination URL (IHyperlinkDestination) I used Facade::IHyperlinkFacade.
UID destUID = ::GetUIDRef(hyperlinkDestination).GetUID();
UIDRef destinationUIDRef = ::GetUIDRef(hyperlinkDestination);
hyperlinkDestination->SetName(URL);
status = Utils<Facade::IHyperlinkFacade>()->ChangeHyperlinkURLDestinationURL(destinationUIDRef, URL);
Thank you for your help.
/Karoly