wxInputStream / Loading HTML to wxRichtextCtrl

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
norisknodisk
Knows some wx things
Knows some wx things
Posts: 43
Joined: Fri Sep 13, 2013 10:24 am

wxInputStream / Loading HTML to wxRichtextCtrl

Post by norisknodisk » Tue Nov 12, 2013 1:00 pm

Hello,

I have a small problem with the wxRichtextCtrl class.

I would like to read an HTML formated string which I previously safed in a database into one of my wxRichtextCtrl elements, in a way that, the HTML formating is respected and shown as such in the wxRichtextctrl. For examlpe: my wxString in the database might be <b>bold</b> hence I would like the Richtextctrl to format "bold" - bold :)

Looking at the manual I came across the LoadFile function of the RichtextBuffer class which I thought is what I want:

LoadFile (wxInputStream &stream, wxRichTextFileType type=wxRICHTEXT_TYPE_ANY)

so I wrote:

Code: Select all

    wxString buf(parent->current_db.get_card(0)->get_topentry());
    rtb = &toptext->GetBuffer();
    wxInputStream* SIStream;
    SIStream->Read((void*)&buf,buf.length());
    rtb->LoadFile(SIStream,wxRICHTEXT_TYPE_HTML);
but the compiler complains:

'bool wxRichTextBuffer::LoadFile(const wxString &,wxRichTextFileType)' : cannot convert parameter 1 from 'wxInputStream *' to 'const wxString &'
1> Reason: cannot convert from 'wxInputStream *' to 'const wxString'

I run windows 7 wxwigets 2.9.5 and included the <wx/stream.h>
why can't the compiler find the second definition ?

Is there another way of solving my problem ? I find streams and "abstract base classes" confusing as hell and try to avoid them whenever possible.

Thank you for your time.

User avatar
doublemax
Moderator
Moderator
Posts: 14277
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxInputStream / Loading HTML to wxRichtextCtrl

Post by doublemax » Tue Nov 12, 2013 2:28 pm

Code: Select all

wxInputStream* SIStream;
SIStream->Read((void*)&buf,buf.length());
This is very wrong on multiple levels. a) you only have an uninitialized pointer to wxInputStream, but no instance. b) You're reading into the wxString memory area, which is not the memory where the actual string is stored.

What you want is to create a wxStringInputStream from the wxString you have:
http://docs.wxwidgets.org/2.8.12/wx_wxs ... nputstream
Use the source, Luke!

norisknodisk
Knows some wx things
Knows some wx things
Posts: 43
Joined: Fri Sep 13, 2013 10:24 am

Re: wxInputStream / Loading HTML to wxRichtextCtrl

Post by norisknodisk » Tue Nov 12, 2013 5:04 pm

Thank you for the fast reply,

I have change my code now to:

whereas toptext, is a wxRichtextCtrl.

Code: Select all

    HTMLhandler = new wxRichTextHTMLHandler();
    rtb = new wxRichTextBuffer();
    rtb->AddHandler(HTMLhandler);

	wxStringInputStream SIStream(parent->current_db.get_card(0)->get_topentry());
	rtb = &toptext->GetBuffer();
	rtb->LoadFile(SIStream,wxRICHTEXT_TYPE_HTML);
althrough everything compiles just fine and there are no runtime errors, "toptext" stays empty - why?

User avatar
doublemax
Moderator
Moderator
Posts: 14277
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxInputStream / Loading HTML to wxRichtextCtrl

Post by doublemax » Tue Nov 12, 2013 5:08 pm

What exactly does the string contain, just something like "<b>bold</b>"? I don't think the loader is prepared to parse single html statements like that. Its purpose is to load a whole document.

For a test, write some bold text into a wxRichTextCtrl, save it as HTML and check what it contains.
Use the source, Luke!

norisknodisk
Knows some wx things
Knows some wx things
Posts: 43
Joined: Fri Sep 13, 2013 10:24 am

Re: wxInputStream / Loading HTML to wxRichtextCtrl

Post by norisknodisk » Tue Nov 12, 2013 5:22 pm

good idea, but even when I tried this ->

wxStringInputStream SIStream(L"<html><head></head><body><b>lalala</b></body></html>");
rtb = &toptext->GetBuffer();
rtb->LoadFile(SIStream,wxRICHTEXT_TYPE_HTML);

it didn't work / which is pretty much what the Richtextctrl sample produces.

User avatar
doublemax
Moderator
Moderator
Posts: 14277
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxInputStream / Loading HTML to wxRichtextCtrl

Post by doublemax » Tue Nov 12, 2013 5:45 pm

After looking into the sources:

a) HTML is an export format only, it can't be loaded. Use the XML format instead.

b) Updating the buffer is not automatically recognized by the wxRichtextCtrl itself. You probably need some more code like this (stolen from the wxRichTextCtrl::DoLoadFile method)

Code: Select all

DiscardEdits();
SetInsertionPoint(0);
LayoutContent();
PositionCaret();
SetupScrollbars(true);
Refresh(false);
IOW: You may have to experiment a bit.
Use the source, Luke!

norisknodisk
Knows some wx things
Knows some wx things
Posts: 43
Joined: Fri Sep 13, 2013 10:24 am

Re: wxInputStream / Loading HTML to wxRichtextCtrl

Post by norisknodisk » Tue Nov 12, 2013 8:11 pm

I can't/don't want to use xml as I have spend considerable time and effort on getting it to work with HTML and use HTML in all parts of the program.
However, I think I will just parse the HTML instead and then work with the richtextctrl->write() beginbold() etc. as the string I want to load really only has three or four parameters.

Thanks for your help.

norisknodisk
Knows some wx things
Knows some wx things
Posts: 43
Joined: Fri Sep 13, 2013 10:24 am

Re: wxInputStream / Loading HTML to wxRichtextCtrl

Post by norisknodisk » Tue Nov 12, 2013 11:17 pm

here is my quick and dirty solution proof of concept function HTML to wxRichtextCtrl in case someone has the same problem.

Code: Select all

void UI_EDITENTRIES::HTMLToRichtextCtrl(long index, wxRichTextCtrl* rtc)
{
	wxString to_parse;
	if(rtc->GetId()==ID_RTCTOP)
	{
		to_parse = parent->current_db.get_card(index)->get_topentry();
	}else if(rtc->GetId()==ID_RTCBOTTOM)
	{
		to_parse = parent->current_db.get_card(index)->get_bottomentry();
	}

	int pos=0;

	bool is_bold = false;
	bool is_italic = false;
	bool is_underlined = false;

	wxString font, size, color, therest;

	wxMessageBox(to_parse);

			wxString toconvert;

    to_parse = to_parse.Mid(to_parse.rfind("face"));
	
	for(int x=0;x<3;x++)
    {
        // first comes font; second size; third color;
        //wxString delimter[] = {"face=", "size=", "style=\"color:"};

        int beg=0, end=0;

        while(end==0)
        {
            if(to_parse[pos]== 0x0022 && beg == 0)  // "
            {
                beg = pos;            // where is the first "
            }
            else if(to_parse[pos]== 0x0022 && end == 0)
              {
                 end = pos;           // here is the second "
              }
            if(beg != 0 && end != 0)        // once we found both
             {
                 if(x==0){ font = to_parse.Mid(beg,(end-beg)+1);  }
                 if(x==1){ size = to_parse.Mid(beg,(end-beg)+1);  }
                 if(x==2){ color = to_parse.Mid(beg,(end-beg)+1); }


      //           to_add = to_parse.Mid(beg,(end-beg)+1); // 
                                                         // the second parameter will be relativ to the first one +1 so we include the second "
             }
        pos++;
        if(font!=L"" && size !=L"" && color !=L"")
        {
            // after we found all the tags we need to get the actual text inclusive the bold italic tags
            therest = to_parse.Mid(pos);
			if(therest.find(L"<b>")!=wxNOT_FOUND){is_bold = true;rtc->BeginBold();}
			if(therest.find(L"<u>")!=wxNOT_FOUND){is_underlined = true;rtc->BeginUnderline();}
			if(therest.find(L"<i>")!=wxNOT_FOUND){is_italic = true;rtc->BeginItalic();}
			

		 toconvert = therest;
                      // this finds out which tag is the closest too the actual information we want
	int pos1 = toconvert.find("<b>");
	int pos2 = toconvert.find("<i>");
	int pos3 = toconvert.find("<u>");

	if((pos1 < pos2) && (pos1 < pos3) && (pos2 < pos3))
	{
		// mid(pos + 3 because the tag consists of three char <x>
		toconvert = toconvert.Mid(pos3+3);
		toconvert = toconvert.Remove(toconvert.find(L"</u>"));
		// pos3 is the is most close to the real data 
	}
	else if((pos1 > pos2) && (pos1 > pos3) && (pos2 > pos3))
	{
		toconvert = toconvert.Mid(pos2+3);
		toconvert = toconvert.Remove(toconvert.find(L"</i>"));
		// pos2 is closest
	}
	else{
		toconvert = toconvert.Mid(pos1+3);
		toconvert = toconvert.Remove(toconvert.find(L"</b>"));
		// pos3 is closest
	} 
		}

		}
	}
	rtc->BeginFont(wxFont(font));
       // #AABBCC = 7
	rtc->BeginTextColour(wxColour(color.Mid(color.find(L"#"),7)));

	rtc->WriteText(toconvert);
	rtc->EndFont();
	rtc->EndTextColour();

	if(is_bold){rtc->EndBold();}
	if(is_italic){rtc->EndItalic();}
	if(is_underlined){rtc->EndUnderline();}


}

Post Reply