I'm new to qt and to c++ and have run into something that I can't solve by searching the internet. First, here is the code in question:
void MainWindow::on_lineEdit_3_textChanged(const QString &arg1) //check for hex or octal
{
QString text = ui -> lineEdit_3 -> text();
QString y = text.mid(0, 1);
int n = text.size();
{
if (y == "0")
{
if (n > 1)
{
text = "Dec. only";
ui -> lineEdit_3 -> setText("");
}
}
}
ui -> lineEdit -> setText(text);
}
This works fine, but when I come back to the editor after running, I have a message at the bottom of the screen:
Unused parameter 'arg1' [-Wunused parameter]
I am sure it is referring to the &arg1 in the first line, however I have no idea what arg1 would be used for or how to use it. Can anyone direct me to information about its use, or tutorial on its use?
From the docs: "This property holds the line edit's text." arg1 must be the current text. For more info, read here.
You're getting that exact message because in your function definition you have const QString &arg1, however you've not used it within your function itself as instead you're retrieving the text with ui->lineEdit_3->text(). The arg1 parameter is the text contained in the ui->lineEdit_3 after it has been changed, so you don't need to retrieve it with the call to ->text().
Side tip, you can squash the warning message with Q_UNUSED(someParameterName), but it flags a warning message for a reason.
This line is not necessary, since you already have the text in arg1.
QString text = ui -> lineEdit_3 -> text();
Then you can use the following to get the first character from the textfield.
QChar y = arg1.at(0);
Related
I am using Qt's QSyntaxHighlighter to color some C like syntax in a QML TextEdit
Everything works great except for multiline comments.
I am detecting them this way :
void highlightBlock(QString const& text) override {
bool inMultilineComment = previousBlockState() == STATES::COMMENT;
bool inSingleLineComment = false;
int previousIndex = 0;
QRegularExpression expr("(\\/\\*|\\*\\/|\\/\\/|\n)"); // will match either /**, /**, // or \n
QRegularExpressionMatchIterator it = expr.globalMatch(text);
while(it.hasNext()) {
QRegularExpressionMatch match = it.next();
const QString captured = match.captured(1);
if(captured == "/*" && !inSingleLineComment) {
inMultilineComment = true;
previousIndex = match.capturedStart(1);
}
if(captured == "*/" && inMultilineComment) {
inMultilineComment = false;
setFormat(previousIndex, match.capturedEnd(1) - previousIndex, _commentFormat);
}
if(captured == "//" && !inMultilineComment) {
inSingleLineComment = true;
}
if(captured == "\n" && inSingleLineComment) {
inSingleLineComment = false;
}
}
if(inMultilineComment) {
setFormat(previousIndex, text.size() - previousIndex, _commentFormat);
setCurrentBlockState(STATES::COMMENT);
}
else {
setCurrentBlockState(STATES::NONE);
}
}
It works until I take a multiline comment already colored and I remove the /* at the begining. Only the block that contains the /* is processed and recolored, but not the following ones, which means that they continue to appear commented when they are not.
Is there an easy way to tell QSyntaxHighlighter to re-process the following blocks to prevent such mis-colorations ?
I ran into this same problem recently and discovered that Qt actually should be handling this for you, assuming that you set your blockState correctly.
If you look at the sourceCode for QSyntaxHighlighterPrivate::reformatBlocks in the Qt5 source code, you'll see
while (block.isValid() && (block.position() < endPosition || forceHighlightOfNextBlock)) {
const int stateBeforeHighlight = block.userState();
reformatBlock(block);
forceHighlightOfNextBlock = (block.userState() != stateBeforeHighlight);
block = block.next();
}
retrieved from https://code.woboq.org/qt5/qtbase/src/gui/text/qsyntaxhighlighter.cpp.html#165
That code (which is fired by a contentsChange signal from the QTextDocument your highlighter is on) will iterate through each block (line) starting from the block that was just modified. Assuming that the state of the block changed based on the typing change that just happened, it will continue to process the following blocks. This means that you need to get your userState correct for every line and Qt should handle the rest.
Given the example
/*
* This is a comment
*
* That I made
*/
You would want to start in the condition where every line had the STATES::COMMENT set except for the last line which should be set to STATES::NONE. Once you do something like deleting the initial /* you need to make sure that the block state is reset to STATES::NONE. That will trigger Qt to rerun the next block, which will also need to change its state, etc.
In my (python) code, I ended up using a combination of print statements and real debugging to track the propagation of state changes and figured out where it was not correctly updating and breaking the chain of updates. Your code looks superficially correct, though I did not try to compile and run it, but I suspect there is a some case being triggered where the state is not being updated correctly after an edit.
I am studying qt - and in the book C++ GUI Programming With Qt 4 I am trying to get all code to work. I am having problems with converting a selection of the contents from a custom table widget into plain text.
existing code in the book:
void MyTableWidget::mouseMoveEvent(QMouseEvent *event)
{
if (event->buttons() & Qt::LeftButton) {
int distance = (event->pos() - startPos).manhattanLength();
if (distance >= QApplication::startDragDistance())
performDrag();
}
QTableWidget::mouseMoveEvent(event);
}
void MyTableWidget::performDrag()
{
QString plainText = selectionAsPlainText();
if (plainText.isEmpty())
return;
QMimeData *mimeData = new QMimeData;
mimeData->setText(plainText);
mimeData->setHtml(toHtml(plainText));
mimeData->setData("text/csv", toCsv(plainText).toUtf8());
QDrag *drag = new QDrag(this);
drag->setMimeData(mimeData);
if (drag->exec(Qt::CopyAction | Qt::MoveAction) == Qt::MoveAction)
deleteSelection();
}
I am trying to write selectionAsPlainText() and deleteSelection().
QTableWidgetSelectionRange MyTableWidget::selectedRange() const
{
QList<QTableWidgetSelectionRange> ranges = selectedRanges();
if (ranges.isEmpty())
return QTableWidgetSelectionRange();
return ranges.first();
}
QString MyTableWidget::selectionAsPlainText()
{
QTableWidgetSelectionRange range = selectedRange();
QList<QTableWidgetItem *> items = selectedItems();
QString str;
for (int i=0;i<range.rowCount();i++){
for (int j=0;j<range.columnCount();j++){
// error on this line
str+=QString(items.at(i*(range.columnCount()-1)+j)->data(Qt::DisplayRole)));
if (j!= range.columnCount()-1)
str += "\t";
}
str += "\n";
}
return str;
}
In this try, out of many, I am attempting to place the items from the QTableWidgetItem in a QString, separated either by "\t" or "\n".
I am unable to try any type of such action because I am getting errors in trying to place any content into the QString.
Everything I have tried so far gives me an error like
conversion from 'QTableWidgetItem* const' to 'QChar' is ambiguous
or
error: no matching function for call to 'QString::QString(QVariant)'
I don't know how to make this type conversion, I have not seen examples on how to specify type casting... Though as I understand it, selecting the Qt::DisplayRole of the data, I should implicitly have a QString...
How can I make this type conversion work ?
I included more code to suggest that the TableWidget is likely of an unknown type.
To begin with, heavily nested parentheses are difficult to read. I would recommend splitting the offending line into several lines. Secondly, the type returned from QTableWidgetItem::data is a QVariant, which can be converted to a QString using the QVariant::toString() member function. Also, I don't think i*(range.columnCount()-1) is quite what you want.
Given this, your code should look something like the following:
int index = i*range.columnCount()+j;
QTableWidgetItem* item = items.at(index);
str += item->data(Qt::DisplayRole).toString();
I'm looking for a clean and cross-platform way to Prevent dropping an item FROM a Qt application TO Windows File Explorer (or other OS equiv.)
The following diagram shows the desired behavior:
I haven't had luck finding examples online or hacking a work-around together, but it seems like it would be a common-enough use-case that there would be a well designed and implemented solution floating around.
What I've tried and do not have working:
Detecting the Drag and Killing It:
detecting the QDragEnterEvent, QDragMoveEvent, QDragLeaveEvent
comparing the answerRect() or pos() of the event to the Geometry of
the Window or Widget to detect if the drag has left the application
This is pretty hacky (and not working at them moment) and I'm hoping you can point me towards a more elegant solution.
(UPDATE - tried changing mimeType, but Windows File Explorer still accepts the drop)
Changing the MIME Type to a custom type:
Pre: the "Widget w/ Drag & Drop" from the diagram above is a QTreeView with a QFileSystemModel model
Sub-classing the QFileSystemModel and overriding the mimeTypes() function like the code below
From the qDebug() output, it looks like the mimeType is correctly being set, but Windows File Explorer still accepts the drop :/
QStringList MyFileSystemModel::mimeTypes() const
{
QStringList customMimeTypes;
customMimeTypes << QString("UnicornsAndRainbows/uri-list");
qDebug() << "customMimeTypes: " << customMimeTypes;
return customMimeTypes;
}
Please let me know when you have a chance.
Thanks! :)
Dmitry Sazonov gave the correct answer. I will explain how I implemented it below. Dmitry, if you want cred, post it as an answer and not a comment so I can accept it as the answer.
What I did wrong on my question update based on Dmitry's suggestion was to override the QFileSystemModel::mimeTypes() when, in fact, I had to modify the QTreeView::mouseMoveEvent() and QTreeView::dropEvent().
//---------------------------------------------------------
void MyTreeView::mouseMoveEvent( QMouseEvent *event )
{
if( !(event->buttons() & Qt::LeftButton) )
{
return; // we only care about left mouse drags at the moment
}
if( (event->pos() - dragStartPosition).manhattanLength() < QApplication::startDragDistance() )
{
return; // a buffer when calculating waht qualifies as a "drag event"
}
QDrag *drag = new QDrag( this );
QMimeData *mimeData = new QMimeData();
QByteArray data;
const QStringList selectedPaths = this->getSelectedPaths(); // custom helper method
foreach( QString path, selectedPaths )
{
data.append( path ).append( ";" ); // using ';' as path deliminator
}
data.chop( 1 );
//--- this sets the custom MIME Type filter
mimeData->setData( CUSTOM_MIMETYPE_STRING, data );
drag->setMimeData( mimeData );
Qt::DropAction dropAction = drag->exec( Qt::CopyAction );
}
//---------------------------------------------------------
void MyTreeView::dropEvent( QDropEvent *event )
{
// ...
QList<QByteArray> paths;
//--- this filters based on our custom MIME Type
paths = event->mimeData()->data( CUSTOM_MIMETYPE_STRING ).split(';');
foreach( QByteArray path, paths )
{
// do something with the file paths
}
}
Is there an option of defining a text and using it later not as a string or anything, just as a part of a function but being able to redefine it in the middle of the program (the definition to not take place in the preprocessor, but runtime)? For example I have the following code in C++ Windows Forms:
private: System::Void ps1_GotFocus(System::Object^ sender, System::EventArgs^ e)
{
if(this->ps1->Text == L"/ Your text here /") this->ps1->Text = L"";
this->ps1->ForeColor = System::Drawing::Color::FromName( "Black" );
}
private: System::Void ps2_GotFocus(System::Object^ sender, System::EventArgs^ e)
{
if(this->ps1->Text == L"/ Your text here /") this->ps1->Text = L"";
this->ps2->ForeColor = System::Drawing::Color::FromName( "Black" );
}
where ps1 and ps2 are TextBoxes and I'm using it to display a gray 'Your text here' string and when clicked in the TextBox ready for input (when the TB GotFocus) to clear the text and make the input black. Having in mind that I have 9 TextBoxes like that, is it possible to make all this with less code? I tried the same code with #define ps ps1 and a global ps_GetFocus() method outside everything that uses that ps, but as you know the #defines are done in the preprocessor and the last define (ps ps9) is defined even before the program is started.
Is there a way of defining non-scoped text at run-time?
Just have a common ps_GotFocus function for all your text boxes, and use sender (you'll have to cast it to the appropriate type first, not sure how to do that in .Net C++ with that weird ^ thingie, maybe dynamic_cast will work?) instead of the various ps objects.
Something along the lines of:
private: System::Void ps_GotFocus(System::Object^ sender, System::EventArgs^ e)
{
TypeForYourTextBox^ the_sender = dynamic_cast<TypeForYourTextBox^>(sender);
// I'm unsure about the previous line but you get the idea
// You may also want to check that the cast succeeded, ie. the_sender is not null
if (the_sender->Text == L"/ Your text here /") the_sender->Text = L"";
the_sender->ForeColor = System::Drawing::Color::FromName("Black");
}
I need to get current page in my document, with set range. I found that it is possible to do by:
Range.Information(wdActiveEndPageNumber) //example in C#
but i have problem with that. In documentation, information is visible as property. So when i use
QString number = myRange->property("Information(wdActiveEndPageNumber)").toString()
i'm getting nothing. I also tried dynamicCall, but either doesn't work. Simple properties as Text or Start works perfectly fine, but i have no idea what to do with these enumerations.
Whole code:
QAxObject *word, *doc;
word = new QAxObject("Word.Application", this);
word->setProperty("DisplayAlerts", false);
word->setProperty("Visible", true);
doc = word->querySubObject("Documents");
doc->dynamicCall("Open(const QString&)", "path to file");
QAxObject *act = word->querySubObject("ActiveDocument");
QAxObject *next = act->querySubObject("Content");
next->dynamicCall("Select()");
next->dynamicCall("Copy()");
QClipboard *clip = QApplication::clipboard();
myTextEdit->setText(clip->text());
QString number = next->property("Information(3)").toString();
QMessageBox::information(this, tr("cos"), tr("%1").arg(number)); //here i need to know how many pages i've got
Okay, after much research, I found that there is no possibility yet to take value from Information enum. Maybe in future version of Qt, but nowadays I had to create library in Visual Basic and invoke functions from C++ code.
Just found a really cool answer to this question here:
http://www.qtforum.org/article/31970/how-do-i-get-use-the-ienumerable-interface-in-qt.html
Here the answer again.
With returnList containing your enum..
QAxObject *enum1 = returnList->querySubObject("_NewEnum");
IEnumVARIANT* enumInterface; //to get this, include <windows.h>
enum1->queryInterface(IID_IEnumVARIANT, (void**)&enumInterface);
enumInterface->Reset(); //start at the beginning of the list.
for (int i=0;i<returnList->dynamicCall("Count").toInt();i++)
{
VARIANT *theItem;
enumInterface->Next(1,theItem,NULL);
QAxObject *item = new QAxObject((IUnknown *)theItem->punkVal);
qDebug() << item->dynamicCall("Caption");
}