I have a little question about Wt. When I create WText (child of a WContainerWidget and having a long long text), Scrollbars are not created for this WText. I have tried many things like setting overflow (with setOverflow function of WContainerWidget), putting this text class into WScrollArea and etc..
If you have some kind of opinions about that problem, I would be glad.
Thanks everyone by now.
Mustafa
Edit: Code example
MyApplication::MyApplication(Wt::WEnvironment const &env)
: Wt::WApplication(env)
{
std::string str = "..." // a very long html string
auto text = new Wt::WText(str, Wt::XHTMLUnsafeText);
root()->setOverflow(OverflowAuto);
root()->addWidget(text);
}
You could use a Wt::WTextArea instead of WText, if its a large file. Its scrollable.
Related
How would i go about formatting text in a rich edit 2.0 control? As of right now i just have a simple little MFC program with a single view and just one rich edit 2.0 control. It's currently empty but i want to insert some text into it.
The control itself is labeled as StringToChange2 and the member within my class is m_StringToChange2.
TCHAR INIValue2[256] = _T("Here is some random text!");
SetDlgItemText(StringToChange2, INIValue2);
So as it stands now, when i run my program it inserts the text into my control. How can i make a word bold from the whole string?
For example i just want it to say : "Here is some random text!"
As it stands now, i can make the whole control bold but I don't want the whole thing to be bold, just a word.
This Link has a very similar question to what I am asking but there is 2 things wrong with it. First, almost all the comments tell him to use a HTML control which i don't want to turn to yet. Second, the one person who did respond to him has such a long snippet of code i don't understand what's happening. The very last answer recommends he use word pad since it uses RTF?
I tried to insert RTF code into my INIValue2 but it won't take it. Unless I'm using it wrong, which could highly be the case.
I've been stalking MSDN and reading the functions, but my level of expertise with MFC and richedit control is very limited. If someone could post a small example of this, it doesn't even have to relate to my question , but something i could use as a base for.
Edit1: It's not that my INIValue2 doesn't take it, it's that when it appears on my single view - it shows everything - including all the RTF code and header.
You have to format the text using EM_SETCHARFORMAT message. In MFC, you can use CRichEditCtrl::SetSelectionCharFormat
First, declare CRichEditCtrl member data in your dialog or window class
CRichEditCtrl m_richedit;
In OnInitDialog put
m_richedit.SubclassDlgItem(IDC_RICHEDIT21, this);
Apply the CHARFORMAT as follows:
CHARFORMAT cf = { sizeof(cf) };
cf.dwEffects = CFM_BOLD;
cf.dwMask = CFM_BOLD;
m_richedit.SetSel(0,2);
m_richedit.SetSelectionCharFormat(cf);
You can use helper functions to make this easier. For example see this post
To assign RTF text directly, you must use EM_STREAMIN. For some reason MFC has no function for this, so you have to write your own function
DWORD __stdcall callback_rtf_settext(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
{
CString *psBuffer = (CString*)dwCookie;
if (cb > psBuffer->GetLength())
cb = psBuffer->GetLength();
for (int i = 0; i < cb; i++)
*(pbBuff + i) = (BYTE)psBuffer->GetAt(i);
*pcb = cb;
*psBuffer = psBuffer->Mid(cb);
return 0;
}
bool setrtf(CRichEditCtrl &edit, const CString &s)
{
EDITSTREAM es;
edit.SetSel(0, -1);
edit.Clear();
memset(&es, 0, sizeof(es));
es.dwCookie = (DWORD_PTR)&s;
es.pfnCallback = callback_rtf_settext;
edit.StreamIn(SF_RTF, es);
return es.dwError == 0;
}
usage:
setrf(m_richedit, L"\\rtf data...");
I want to change the size of the help window to fit the size of the text, but don't know how to proceed.
Here is my code :
QTextEdit *help = new QTextEdit(this);
help->setWindowFlags(Qt::Window);
help->setReadOnly(true);
////
QFile file(":/help.txt");
QTextStream stream ( &file );
QString line;
if (!file.open (QIODevice::ReadOnly))
{
//some error report
}
while( !stream.atEnd() ) {
line = stream.readLine();
help->append(line);
}
file.close();
help->show();
You need some layout information about your text because, in theory, it could be rendered in one really, really long line.
So, I would aim for some target width of the text while all text being wider than that will be wrapped. Now, what you need is the height for that kind of text.
My suggestion would be that you use a QTextDocument, set the width as described above, insert all the text and get the size using QTextDocument::size. That way, you get the measures and can resize your window to those (adding margin, padding etc., of course).
I'm making a simple code text editor in Qt where it picks up C++ keywords and colors them. I know that Qt has a foreach function, but how can I use it live with the QTextEdit that the user is typing into?
Here is what I have tried, where if I type the word Hi into the textEdit then it pops up in the debug. This didn't work.
QLinkedList<QTextEdit* > list;
QString str = "Hi";
foreach(str, list)
qDebug() << str;
I think I saw this idea somewhere on a forum, but again it didn't work. If you can help out, any suggestions are helpful! Thanks!
Edit:
Here's what I have now:
QString text = ui->textEdit->toPlainText();
QString str = "Hi";
foreach(str, text)
qDebug() << str;
Except qDebug() outputs Hi every time I print a character rather than when I print all of Hi
I have no idea why you have a list of QTextEdits but to get your code to compile, you have to do like below.
QLinkedList<QTextEdit*> list;
QTextEdit* textEdit = NULL;
foreach(textEdit, list)
qDebug() << textEdit->toPlainText();
The problem with your code is that you are trying to assign a QTextEdti* to a QString.
Answer to the question asked in the comment:
Connect textChanged() signal of textEdit to a slot.
connect(textEdit, SIGNAL(textChanged()), SLOT(onTextChanged()))
In the slot, split the text in textEdit with space character and iterate.
private void MyWnd::onTextChanged()
{
QStringList wordList = textEdit->toPlainText().split();
foreach (QString word, wordList )
{
qDebug() << word;
}
}
OMG you doing that completely wrong and asking for solution which doesn't help in your problem in fact it makes it even worse.
Also all you need is documented in Qt.
Check this Qt example.
I am using Gtkmm 3+ and What I am trying to do is have the text buffer have the constant string "> " even if the user tries to delete it. In addition when the user pressed return it will automatically be there again. Basically have a constant string like a terminal does.
The only way I can think about about accomplishing this would be to connect to the delete and backspace signals so the user cannot delete the string. But, is there a better way?
so far this is the only way I can think of:
//in constructor
txt_view_i_.signal_event().connect(sigc::mem_fun(*this, &MainWindow::inputEvent));
//function
bool MainWindow::inputEvent(GdkEvent* event)
{
if((event->key.keyval == GDK_KEY_BackSpace || event->key.keyval == GDK_KEY_Delete) && buffer_input_->get_char_count() < 3)
return true;
return false;
}
But doesn't work perfectly, because if you type in more then 3 characters then go to the beginning of the line you can delete the constant string.
Another way I just thought about was to add a label to the TextView widget. I did that but, the user could still delete it. Here is the code for that:
Gtk::TextBuffer::iterator it = buffer_input_->get_iter_at_line(1);
Glib::RefPtr<Gtk::TextChildAnchor> refAnchor = buffer_input_->create_child_anchor(it);
Gtk::Label* lbl = Gtk::manage(new Gtk::Label("> "));
txt_view_i_.add_child_at_anchor(*lbl, refAnchor);
This is very similar, but not quite identical, to the question I answered here: You can create a GtkTextTag that makes its contents uneditable, and apply it from the beginning of the buffer up to and including the "> " prompt.
Then when you receive input, append your output to the buffer and then append a new prompt on the next line, and re-apply the tag to make the whole thing uneditable.
The links in the linked answer show some C code where this is done, even including a prompt. It's not Gtkmm or C++, but it should serve as an illustration.
Here is the code I used to solve it:
Glib::RefPtr<Gtk::TextBuffer::Tag> tag = Gtk::TextBuffer::Tag::create();
tag->property_editable() = false;
Glib::RefPtr<Gtk::TextBuffer::TagTable> tag_table = Gtk::TextBuffer::TagTable::create();
tag_table->add(tag);
buffer_input_ = Gtk::TextBuffer::create(tag_table);
txt_view_i_.set_buffer(buffer_input_);
scroll_win_i_.add(txt_view_i_);
Gtk::TextBuffer::iterator buffer_it_ = buffer_input_->begin();
buffer_input_->insert_with_tag(buffer_it_, "> ", tag);
Here is how I made it so that the user cannot edit before the constant string:
//connect to the mark set signal
buffer_input_->signal_mark_set().connect(sigc::mem_fun(*this, &MainWindow::setMark));
//make the box uneditable
void MainWindow::setMark(const Gtk::TextBuffer::iterator& it, const Glib::RefPtr<Gtk::TextBuffer::Mark>& mark)
{
if(it.get_offset() < 2)
txt_view_i_.set_editable(false);
else
txt_view_i_.set_editable(true);
}
Hopefully someone will find this useful.
Update
void MainWindow::readXml()
{
QDomDocument Champions;
QFile xmlFile("champions.xml");
xmlFile.open(QIODevice::ReadOnly);
Champions.setContent(&xmlFile);
QDomElement root = Champions.firstChildElement();
QDomNodeList ChampionNames = root.elementsByTagName("Champion");
for(int i = 0; i < ChampionNames.count(); i++)
{
QDomNode championNode = ChampionNames.at(i);
if(championNode.isElement())
{
QDomElement Champion = championNode.toElement();
ui->comboBox->addItem(Champion.attribute("Name"));
}}}
Managed to get something like this so I've the names in the comboBox now :)
I'm new to this community so I'm happy to meet all of You!
First I want to inform You that I'm pretty new to Qt programming however I've had some basic c++ lessons in school though it was only console programming and I've never worked on stuff like that. Why I've started with Qt? It looked easy to me and hell it was compared to visual studio! So here is my problem.
Basiclly I have a comboBox where I would read my "Name="" " attributes in. There will be around 100 maybe abit less maybe a bit more don't know Yet. I don't know how to start with everything this since I have never done such thing before. What i want the software to do is basiclly when i select a "name" in the combobox, i want all the attributes ("Q" "W" "E" "R") to be printed out in the 4 labels as You can see on the little image I've added.
I don't know if I need to first read the file into some strings arrays or data structures. Do I need to search the XML file for the "Name" which is selected in ComboBox and then somehow print it out? I spent some time on this but I cant find a way to achive the thing I want. I would really appriciate some code exemples specially using the ComboBox since as said I'm new to this.
XML File looks like this in case image is blurry:
<ROOT>
<Champ Name="XXX1">
<Q>QQ1</Q>
<W>WW1</W>
<E>EE1</E>
<R>RR1</R>
</Champ>
<Champ Name="XXX2">
<Q>QQ2</Q>
<W>WW2</W>
<E>EE2</E>
<R>RR2</R>
</Champ>
</ROOT>
I'm really bad on describing things so I've made a small ilustration using a pen to let You understand me better :)
My beautiful sketch.
Thanks for Your support in advance! Hope I'm clear enought with my question. Have a great day.
First you should represent your XML data as a C++ class/struct:
class Champ {
public:
// A constructor using QDomElement as argument
Champ(QDomElement element);
QString name;
QString q, w, e, r;
};
Second you should load the XML file, parse it, and populate a vector (or map) with Champ objects.
QVector<Champ> loadChampsObjects(const QString& xmlPath)
{
QVector<Champ> champObjects;
QFile file(xmlPath);
if (!file->open(QIODevice::ReadOnly | QIODevice::Text))
return champObjects;
/* QDomDocument takes any QIODevice. as well as QString buffer*/
QDomDocument doc("mydocument");
if (!doc.setContent(file))
return champObjects;
//Get the root element
QDomElement docElem = doc.documentElement();
// get the nodes we need
QDomNodeList nodeList = docElem.elementsByTagName("champ");
// Check each node create a Champ object and add it the vector...
for(int i = 0; i < nodeList.count(); i++)
champObjects.append(Champ(nodeList.at(i).toElement()));
return champObjects;
}
Third populate the QComboBox. We will use the index in vector as userData:
QVector<Champ> champObjects = loadChampsObjects("path.to.xml");
for (unsigned i=0; i<champObjects.count(); i++)
pComboBox->addItem(champObjects[i].name, QVariant(i));
Finally in the slot connected to the currentIndexChanged signal of combo box you can easily access the properties of the selected object using the userData that indicated the index in the vector:
void champObjectChanged()
{
unsigned vectorIndex = pComboBox->itemData(pComboBox->currentIndex())->toInt();
Champ c = champObjects[vectorIndex];
// do whatever you want with it
}
Use Qt's DOM components to do all the parsing and tree building for you (see the examples here for their use).
For the QComboBox, once the QDomDocument is complete you can search for all your Champ nodes and read the Name attributes off of them. For each one, just use QComboBox::addItem(const QString& text) to add them.
Then connect the QComboBox::currentIndexChanged (const QString&) signal to a method in your XML handling class that searches the DOM tree for a Champ node with a Name attribute that matches it. Once found read off each one of it's child node values (that's the 'Q', 'W', 'E', 'R' values).