Jak usuwać tekst QTextEdita usuwając tekst w innym QTextEdicie?

0

Cześć,
sorka za dość pogmatwany tytuł, nie wiem jak to inaczej wytłumaczyć :P
Mam dwa textedity: w jednym sobie użytkownik pisze co chce, a w drugim wyświetla się przetłumaczony kod morsa. Działa w porządku poza jedną rzeczą: nie mam bladego pojęcia jak usuwać tekst z drugiego textedita jeśli użytkownik usuwa tekst w pierwszym. Np.:
User input(QTextEdit) : dupa =>
Converted(QTextEdit) : _.. .._ .__. ._
Jeśli usunę a w pierwszym TextEdicie:
User input(QTextEdit) : dup =>
Converted(QTextEdit) : _.. .._ .__.
Myślałem nad użyciem QString::remove(), ale skąd będę wiedział co usunąć? Może napisać jakiś stos i wrzucać na niego input użytkownika, a jak usunie tekst, to zdjąć z niego wartość zaczynając od ostatniej? Tyle, że to się sypnie jak user usunie tekst z innego miejsca niż końca...
Metoda w której wszystko się dzieje:

void MainWindow::on_textEdit_textChanged()
{
    //if (uzytkownik usuwa tekst)
        //usun tez tekst z innego TextEdita. 
    std::string stdText = ui->textEdit->toPlainText().toStdString();
    if (!stdText.empty()) {
        char lastCharacter = stdText[stdText.length() - 1];
        if (isspace(lastCharacter))
            ui->textEdit_2->insertPlainText("     ");

        ui->textEdit_2->insertPlainText(morseCodes[toupper(lastCharacter)] + "  ");
    }
}

Pewnie jakbym przeczytał jakąś książkę o Qt5, to bym znał rozwiązanie, bo pewnie jest proste jak drut :P
Pozdro!

1

Najłatwiej po prostu podpiąć się do sygnału textChanged() i wygenerować kod Morse'a jeszcze raz. Jak koniecznie chcesz bawić się w diffy, to powodzenia z zabawą.

0

Hej, w sumie to jest też niezłe rozwiązanie i chyba najprostsze w implementacji. Boję się tylko o wydajność, ale to chyba bez znaczenia dla zadania takiego "kalibru". Dzięki za propozycję.

0

eh tak myślałem, wydajność jest do pupy jak implementuję tę funkcję w ten sposób. Im więcej tekstu tym więcej zasobów jest zużywane, aż w pewnym momencie jest jakiś 1 fps XD
Zmieniona funkcja, którą wywołuję za każdym sygnałem textChanged():

void MainWindow::convertToMorseCode() {
    ui->convertedText->clear();
    std::string stdText = ui->userText->toPlainText().toStdString();
    for (const auto &character : stdText) {
        if (auto found = std::find_if(
                morseCodes.begin(), morseCodes.end(),
                [&character](const auto &value) { return toupper(character) == value.first; });
            found != morseCodes.end())
            ui->convertedText->insertPlainText((found->second) + "  ");
    }
}

generowanie całego kodu za każdym razem na nowo chyba nie wchodzi w grę, a co ciekawe, to zauważyłem, że program zużywa do 30% procesora i więcej już nie, dlaczego? Coś czuję, że do zaorania jest ta pętla :D

1

Po pierwsze wydziel logikę Morsa do osobnej klasy.
Np coś w tym stylu:

class MorseTextConverter : public QObject
{
    Q_OBJECT

    Q_PROPERTY(text READ text WRITE setText NOTIFY textChanged)
    Q_PROPERTY(morse READ morse WRITE setMorse  NOTIFY morse Changed)

public:
    using QObject::QObject;

    void setText(const QString& text);
    QString text() const;

    void setMorse(const QString& morse);
    QString morse() const;

public signals:
    void textChanged(const QString&);
    void morseChanged(const QString&);

private:
     ....
};

potem podłączasz tylko sygnały i sloty do UI i gotowe

0

Prosty przykład projektu Qt z wykorzystaniem TextEdit , TextBrowser i on_textEdit_textChanged

mainwindow.h

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void on_textEdit_textChanged();

private:
    Ui::MainWindow *ui;

    QString convert( const QString& );
};

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <map>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::on_textEdit_textChanged()
{
   ui->textBrowser->setText( convert(ui->textEdit->toPlainText() ) );
}

QString MainWindow::convert( const QString& word )
{
    QString result {""};

    static const std::map<const QChar,const QString> morse = {
                                                                 {'a',"*-"},
                                                                 {'b',"-***"},
                                                                 {'c',"-*-*"}
                                                                 // resztę należy wpisać
                                                              };

    for( const auto& letter : word.toLower() )
    {
        if( morse.find(letter)==morse.end() ) return "invalid text";
        result += ( morse.at(letter) + " " );
    }

    return result;
}
0

Dobrze, dziękuję wszystkim za pomoc, dostałem to, co chciałem: tekst się usuwa i dzięki konkatenacji 50000 razy wydajniej niż to było wcześniej (na podstawie kodu od @TomaszLiMoon). Wrzucę kod jakby ktoś chciałby osiągnąć coś podobnego co ja:

void MainWindow::on_userText_textChanged() {
   ui->convertedText->clear();
   ui->convertedText->insertPlainText(MorseCodeConverter::TextToCode(ui->userText->toPlainText()));
}
QString MorseCodeConverter::TextToCode(const QString &text) {
    QString converted{""};
    for (const auto &character : text.toStdString()) {
        if (auto found = std::find_if(
                morseCodes.begin(), morseCodes.end(),
                [&character](const auto &value) { return toupper(character) == value.first; });
            found != morseCodes.end())
            converted.append(found->second);
    }
    return converted;
}

Implementacja nadal nie jest perfekcyjna, bo po zapełnieniu tego QTextEdita dużą ilością tekstu, to i tak wydajność spada, ale i tak jest już o niebo lepiej. Dzięki za pomoc.

0

Na pewno możesz dodać tam wywołanie QString::reserve() przed dodawaniem. Alternatywnie, zobacz jak się sprawuje QTextStream. Przy czym to cały czas jest algorytm O(n), więc będzie O(n) i tak i tak.

1 użytkowników online, w tym zalogowanych: 0, gości: 1