2010-12-17 12 views
6

Sto utilizzando la libreria Qt Property Browser come editor di record. Quando l'utente ha completato le modifiche di un determinato campo, rimuovendo lo stato attivo dall'elemento di modifica o premendo il tasto Invio, voglio essere informato di ciò in modo che possa prendere la modifica, elaborarla e inviarla al REAL oggetto che è stato cambiato.QtPropertyBrowser e valore cambiato segnali

Purtroppo mi sembra di essere solo in grado di trovare i segnali PropertyChanged e ValueChanged e ottengono attivato ogni volta che viene aggiunto o rimosso, non solo quando l'utente sta provocando una finitura qualsiasi quantità di testo.

Senza poter ricevere questa notifica, non vedo come questo possa essere un componente utilizzabile. Non viene nemmeno ripristinato quando l'utente preme [ESC], che devo certamente essere in grado di implementare! Sicuramente devo sbagliarmi sul fatto che non c'è assolutamente alcun segnale che faccia ciò di cui ho bisogno, ma di certo non riesco a trovarlo.

Qualcuno sa?


Dopo aver esaminato il codice sorgente, le persone che hanno fatto la fabbrica line ha reso la sfortunata decisione di connettersi con textEdited piuttosto che editingFinished. Sarebbe una questione relativamente semplice da cambiare, tranne che il fatto abbastanza metodicamente ha reso impossibile estendere questa fabbrica di editor che ha un'interfaccia estensibile!

Tutto quello che dovrei fare è sovrascrivere la funzione createEditor, disconnettere la connessione non valida, connettere una connessione migliore con una chiamata in mezzo per ottenere la stringa fuori dal controllo di modifica della linea. Ma no!!! Non ti lasceremo fare! Metteremo tutte le cose contabili in una classe privata a cui non è possibile accedere o chiamare e quelle parti che lasceremo chiamare saranno strettamente associate al fatto che vengono chiamate dal modifica il controllo, NON da altro. ERGO, abbiamo reso la vita abbastanza frustrante impossibile da immaginare. Non siamo brillanti?


ho scoperto di più. L'approccio Qt standard per questi tipi di oggetti utilizza i delegati per controllare il comportamento che sto cercando di ottenere. La libreria di proprietà Qt sovrascrive questo comportamento e fa qualcos'altro che NON è quello che sto cercando di realizzare. All'interno dell'interfaccia QAbstractItemDelegate c'è una funzione setModelData chiamata dalla vista a cui è collegato quando l'utente esegue le modifiche; non viene chiamato quando distruggono l'editor senza commetterlo.

Il trucco successivo sarà l'apprendimento del modello Qt/Visualizza l'architettura e il patching della libreria per farlo nel modo giusto. Questo potrebbe anche non essere altro che la semplice rimozione degli stub sovrascritti che distruggono il comportamento che sto cercando di ottenere. Potrebbe anche essere che rinunciare all'uso di questo sistema al posto di usare semplicemente QtTreeView potrebbe essere una scelta migliore anche se sarebbe bello poter mantenere la possibilità di cambiare tra i diversi tipi di browser.

+1

5 anni dopo e ho avuto la stessa sensazione di te. Ho fatto molti hack per rendere la griglia delle proprietà almeno un po 'come quella di .NET. – Jack

risposta

4

Quindi, ecco la correzione a metà-ass mi si avvicinò con:

Ho aggiunto una funzione "commitItem (QModelIndex)" per la cosa privata nel TreePropertyBrowser. Quindi lo chiamo dal delegato quando viene chiamata la funzione setModelData().

Questo trova la proprietà, chiama una nuova funzione che ho aggiunto a AbstractBrowser per recuperare la factory per una proprietà e poi dice la factory a "commitProperty (QtProperty *)".

Questa funzione è un virtuale vuoto alla base e in LineEditFactory lo sovrascrivo per applicare la modifica della proprietà, che genera il segnale valueChanged().

Con questi cambiamenti in atto l'utente è in grado di recedere dal modifica premendo il tasto ESC e riceve la notifica se e solo se commettono il cambiamento di proprietà colpendo RETURN, concentrarsi cambiando, ecc ...

Solo al momento lavora per la versione ad albero. Probabilmente non si preoccuperà di cercare di far funzionare il resto. In effetti probabilmente sto per buttare via questa libreria e usare solo QTreeView. L'IT si comporta come voglio io, questa cosa doveva essere uber-hacked per ottenere il comportamento INDIETRO.

Oh sì, è anche necessario rimuovere la connessione al segnale textChanged() in createEditor di LineEditFactory().

1

Mi sono imbattuto in questo stesso problema un po 'di tempo fa. Avevamo bisogno di sapere quando il montaggio era finito per qualcuno degli editori di QVariant. Il trucco è che il framework crea ed elimina i suoi widget mentre si avvia e si interrompe la modifica. Quindi, sepolto nelle classi di EditorFactory, mi sono collegato a QObject :: signal distrutto ogni singolo tipo di QWidget che ha creato, e ho gorgogliato un nuovo segnale propertyEditFinished che l'app principale può catturare.

QtPropertyBrowser è decisamente pazzo, ma è anche doloroso reimplementare il tutto.

+0

In realtà, ho scoperto che non era necessario molto lavoro da implementare e ho qualcosa che ha un po 'più senso. Il browser delle proprietà (la parte che volevo comunque) non è altro che una vista ad albero di base. –

+0

Sì, hai ragione. Questa è la cosa dell'ingegneria. Quello che dovrebbe essere fatto o ciò che è più facile torna sempre a ciò che devi veramente fare. :) È una buona cosa che siamo pigri! Sono contento che tu abbia funzionato. – Thadeux

1

Questa domanda probabilmente non è più rilevante in Qt 5 che ha incorporato QtPropertyBrowser e gli amici. Ho implementato un segnale editingFinished per QtLineEditorFactory lungo le linee di Thadeaux's approach, quindi ho deciso che non avevo bisogno/voglio farlo in quel modo! Forse per placare la sensazione di sprecare il mio tempo accludo un codice diff della mia soluzione nel caso qualcuno possa trovarlo utile.

Index: src/qteditorfactory.cpp 
    =================================================================== 
    --- src/qteditorfactory.cpp (revision 737) 
    +++ src/qteditorfactory.cpp (working copy) 
    @@ -1076,7 +1076,6 @@ 
    } 


    - 
    /*! 
     \class QtLineEditFactory 

    @@ -1094,7 +1093,6 @@ 
    { 
     d_ptr = new QtLineEditFactoryPrivate(); 
     d_ptr->q_ptr = this; 
    - 
    } 

    /*! 
    @@ -1121,6 +1119,10 @@ 
       this, SLOT(slotEchoModeChanged(QtProperty *, int))); 
     connect(manager, SIGNAL(readOnlyChanged(QtProperty*, bool)), 
      this, SLOT(slotReadOnlyChanged(QtProperty *, bool))); 
    + 
    + // c.s. Added 4/12/2017 
    + connect(this, SIGNAL(propertyEditingFinished(QtProperty*, const QString&)), 
    +  manager, SIGNAL(propertyEditingFinished(QtProperty*, const QString&))); 
    } 

    /*! 
    @@ -1131,7 +1133,6 @@ 
    QWidget *QtLineEditFactory::createEditor(QtStringPropertyManager *manager, 
      QtProperty *property, QWidget *parent) 
    { 
    - 
     QLineEdit *editor = d_ptr->createEditor(property, parent); 
     editor->setEchoMode((EchoMode)manager->echoMode(property)); 
     editor->setReadOnly(manager->isReadOnly(property)); 
    @@ -1146,9 +1147,49 @@ 
        this, SLOT(slotSetValue(const QString &))); 
     connect(editor, SIGNAL(destroyed(QObject *)), 
        this, SLOT(slotEditorDestroyed(QObject *))); 
    - return editor; 
    + 
    + // c.s. Added 4/12/2017 
    + connect(editor, SIGNAL(editingFinished()), SLOT(handleEditingFinished())); 
    + return editor; 
    } 

    + 
    + 
    +// c.s. Added 4/12/2017 
    +void QtLineEditFactory::handleEditingFinished() 
    +{ 
    + auto keys = d_ptr->m_editorToProperty.keys(); 
    + QLineEdit *le = qobject_cast<QLineEdit*>(sender()); 
    + if (!le) 
    +  return; 
    + 
    + disconnect(le, SIGNAL(editingFinished()), this, SLOT(handleEditingFinished())); 
    + 
    + QtProperty *property = 0; 
    + 
    + const QMap<QLineEdit *, QtProperty *>::ConstIterator ecend = 
    +  d_ptr->m_editorToProperty.constEnd(); 
    + for (QMap<QLineEdit *, QtProperty *>::ConstIterator itEditor = 
    +   d_ptr->m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor) 
    + { 
    +  if (itEditor.key() == le) 
    +  { 
    +   property = itEditor.value(); 
    +   if (!property) 
    +    return; 
    +   
    +   QtStringPropertyManager *manager = propertyManager(property); 
    + 
    +   if (!manager) 
    +    return; 
    + 
    +   QString s = manager->value(property); 
    +   manager->setValue(property, s); // make sure it has the last value 
    +   emit propertyEditingFinished(property, s); 
    +  } 
    + } 
    +} 
    + 
    /*! 
     \internal 

    @@ -1165,6 +1206,9 @@ 
     disconnect(manager, SIGNAL(readOnlyChanged(QtProperty*, bool)), 
      this, SLOT(slotReadOnlyChanged(QtProperty *, bool))); 

    + // c.s. Added 4/12/2017 
    + disconnect(this, SIGNAL(propertyEditingFinished(QtProperty*, const QString&)), 
    +  manager, SIGNAL(propertyEditingFinished(QtProperty*, const QString&))); 
    } 

    // QtDateEditFactory 
    Index: src/qteditorfactory.h 
    =================================================================== 
    --- src/qteditorfactory.h (revision 737) 
    +++ src/qteditorfactory.h (working copy) 
    @@ -183,6 +183,14 @@ 
     QWidget *createEditor(QtStringPropertyManager *manager, QtProperty *property, 
        QWidget *parent); 
     void disconnectPropertyManager(QtStringPropertyManager *manager); 
    + 
    +// c.s. Added 4/12/2017 
    +Q_SIGNALS: 
    + void propertyEditingFinished(QtProperty*, const QString&); // signal editing done in line_editor is finished 
    + 
    +protected slots: 
    + void handleEditingFinished(); // similar to QLineEdit 
    + 
    private: 
     QtLineEditFactoryPrivate *d_ptr; 
     Q_DECLARE_PRIVATE(QtLineEditFactory) 
    Index: src/qtpropertymanager.h 
    =================================================================== 
    --- src/qtpropertymanager.h (revision 737) 
    +++ src/qtpropertymanager.h (working copy) 
    @@ -200,6 +200,9 @@ 
     void echoModeChanged(QtProperty *property, const int); 
     void readOnlyChanged(QtProperty *property, bool); 

    + // c.s. Added 4/12/2017 
    + void propertyEditingFinished(QtProperty *, const QString &val); 
    + 
    protected: 
     QString valueText(const QtProperty *property) const; 
     QString displayText(const QtProperty *property) const;