Seite 1 von 1

Mehrfachauswahl über QFileDialog + Ordner rekursiv auslesen

Verfasst: 8. Juni 2005 16:21
von ron
Hallo zusammen

In Bezug auf die Mehrfachauswahl von Dateien UND Verzeichnisse
über QFileDialog und dem rekursiven auslesen von Verzeichnissen
hatte ich hier im Forum gepostet und eine Lösung gefunden.
(Danke Christian !)

Über google fand ich dahingehend lediglich die gleichen Fragen von Entwicklern statt Antworten.
Auch hier im Forum wird ja viel nach der "gemischten Mehrfachauswahl"
über QFileDialog gefragt, daher stelle ich hier mal ein snipped ein.

Problemstellung:
----------------------------------------------------------------------------------------------
Über QFileDialog Dateien und/oder Verzeichnisse auswählen und
die Dateinamen (inklusive Pfad) in einem QStringList Objekt
ablegen. Verzeichnisse sollen rekursiv (also auch deren Unterverzeichnisse) durchsucht werden und in einer ListView angezeigt werden.

SLOT: void onAdd();

Funktionen:
void onAddFiles( QString files );
void onAddFolders( QString folders );
void onUpdateList();

Variablen:
QStringList m_fileList;
QListView m_ctrlFileView;

Klasse: MainFrm ( mainfrm.cpp, mainfrm.h )

Code: Alles auswählen

/**
 QFileDialog aufrufen, Dateien/Verzeichnisse wählen
 und ermittelte Werte an 'onAddFiles( QString files )'
 übergeben
*/
void MainFrm::onAdd()
{
    QStringList filterlist;
    QString filters = filterlist.join( ";;" );
    QStringList filenames;
    filenames = QFileDialog::getOpenFileNames( filters, QString::null, this, 0, tr("Add") );  
    QStringList::Iterator it = filenames.begin();
    
    while( it != filenames.end() )
    {
	// m_fileList füllen
	onAddFiles( *it );
	++it;
    }
    onUpdateList();
    filenames.clear();
}

/**
 den in "file" übergebenen Wert in m_fileList ablegen,
 wenn Verzeichniss dann onAddFolders( QString folders )
 aufrufen.
*/
void MainFrm::onAddFiles( QString file )
{
    QFileInfo f( file );
    
    if ( f.isFile() )
    {
	//wir wollen Dateiname + Pfad
	m_fileList.append( f.absFilePath() );
    }
    else if ( f.isDir() )  
    {
	onAddFolders( file );
    }
}

/**
 Verzeichniss auslesen, wenn Unterverzeichniss
 auch deren Inhalt ermitteln und an m_fileList
 anhängen
*/
void MainFrm::onAddFolders( QString folder )
{
    QDir d ( folder );
    if ( !d.exists() ) 
    {
	QMessageBox::information( this, "Error", "Can't open folder");
	exit( 1 );
    }
    
    d.setFilter( QDir::Dirs | QDir::Files | QDir::Hidden | QDir::NoSymLinks );
    d.setMatchAllDirs( true );
    
    const QFileInfoList *list = d.entryInfoList();
    QFileInfoListIterator it( *list );
    QFileInfo *fi;
    
    for ( ; ( fi = it.current() ) != 0; ++it )
    {
	// "." und ".." brauchen wir nicht..
	if ( fi->fileName() == "." || fi->fileName() == ".."  )
	    continue;
	else if ( fi->isDir() )
	    // win-user benutzen nat. "\\"
	    onAddFolders( fi->absFilePath() + "/" );
	else if( fi->isFile() ) 
	    m_fileList.append( fi->absFilePath() );
    }
}

/**
 Listenansicht aktualisieren und ermittelte
 Dateien anzeigen
*/
void MainFrm::onUpdateList()
{
	QStringList::Iterator it = m_fileList.begin();	  
	while( it != m_fileList.end() ) 
	{
	 QListViewItem *item = new QListViewItem( m_ctrlFileView );
	 item->setText( 0,  *it ); // Column 0 = "Filename"	
	 ++it;
        }
}
So das war's auch schon, -bleibt die Frage: Wofür das ganze ?
Nun, manchmal ist es nötig Dateien zu einem Archiv zusammen zu packen,
Dateien nach einem bestimmten Inhalt zu durschsuchen, Dateien eines
Ordners mit dem eigenem Algorithmus sicher zu löschen u.s.w., u.s.w.

Also dann, hoffe ich konnte ein parr offene Fragen der Gemeinde klären,

ron

Re: Mehrfachauswahl über QFileDialog + Ordner rekursiv ausle

Verfasst: 8. Juni 2005 21:38
von Christian81
ron hat geschrieben:

Code: Alles auswählen

...
	    // win-user benutzen nat. "\"
	    onAddFolders( fi->absFilePath() + "/" );
...
Oder noch besser, man nimmt die Qt-eigene Funktion char QDir::separator (). Des weiteren konvertiert Qt bei den Zugriffen auf die OS-spezifischen Dateifunktionen die Separatoren automatisch so das man im Grunde immer nur '/' zu nehmen braucht.

Verfasst: 9. Juni 2005 12:05
von dani.80
versteh ich das richtig? Hier soll es möglich sein, auch mehrere Ordner über den QFileDialog auszuwählen?
Wenn ich das mit getOpenFileNames realisiere, kann man doch wieder nur Dateien auswählen, oder?
Habs scheinbar noch nicht ganz verstanden :-(.

Verfasst: 10. Juni 2005 10:27
von ron
Ja, mit oben angeführtem Code ist es möglich, Dateien UND Ordner gleichzeit zu selektieren.
Das ganze funktioniert genauso wie im Designer unter "Project"->"Add...".

2 Methoden:

1.
wenn Du QFileDialog aufgerufen hast, nicht direkt mit der Maus einen Eintrag
markieren, sondern den Mauszeiger einfach neben einem Eintrag, -
linke Maustatste drücken, Taste gedrückt halten und über die gewünschten Dateien und/oder Ordner ziehen.

oder 2.
Eine Datei direkt markieren und dann mit Shift+Pfeiltaste weitere auswählen.

Das wars..

MfG ron :wink:

Verfasst: 10. Juni 2005 13:56
von dani.80
Danke für die Erklärungen.
Aber ich kann - auch mit der Methode, die du beschrieben hast - auf diese Weise trotzdem nur Dateien auswählen. Auch im Qt-Designer über Project -> AddFiles ist es nur moeglich Dateien auszuwählen. Mach ich irgendwas falsch?
Ich verwende Qt-Version 3.3.4.

Wär echt schön, wenn das klappt, aber irgendwie hab ichs noch nicht hinbekommen :-(.

Verfasst: 10. Juni 2005 14:46
von ron
hi dani !

Mein Entwickler System:
SuSE Linux 9.3
QT-Version: 3.3.4
------------------------------------
( privat SLACKWARE 10.0 )
-----------------------------------

...so wie beschrieben ! !

Ehrlich gesagt weiss ich nicht wo es bei Dir hängt.
Gib doch einfach mal das Stück Code rüber, in welchem Du
selektieren willst !

Auf Wunsch senden ich Dir auch gerne eine Beispiel-App (nat. Source) !

Mal am Rande:
Welches OS benutzt Du ?
Wenn Linux/KDE, - öffnet sich der QFileDialog oder der KFileDialog ??
Es sollte KFileDialog sein.

Wenn Windows sollte es auch klappen, jedenfalls nach Probe auf dem
Rechner meiner Tochter Win2000/XP-Pro und Home

MfG ron :?

Verfasst: 10. Juni 2005 15:10
von dani.80
Hi Ron,
vielen Dank. Deine Beispiel-Applikation hätte ich natürlich gerne.
email: einfach ein @gmx.de hinter meinen User-Namen.
Ja, ich verwende Linux / KDE. Mal ne blöde Frage, woran sehe ich ob sich um einen KDE-FileDialog handelt, oder nicht.
Also das was ich mache, ist eigentlich nur, deine onAdd() Methode als Slot zu definieren (wie du es ja auch vorgeschlagen hast) und diesen Slot verknüpfe ich mit einem Button. Mehr nicht.

Hm...

Liebe Grüße,
Dani

:wink:

Verfasst: 10. Juni 2005 15:40
von ron
Hi dani

Die Beispiel-App sende ich Dir gerne zu und
sollte in der nächsten Stunde bei Dir sein...

Wir bekommen das schon hin !

MfG ron

PS:
Ein KFileDialog öffnet sich z.B. bei "kwrite"->"Open", wie unter KDE gewohnt,
ein normaler QFileDialog öffnet sich zum Beispiel hier:

Code: Alles auswählen

void MainFrm::onOpen()
{
    QFileDialog* fd = new QFileDialog( this, "Open", TRUE );
    fd->setMode( QFileDialog::AnyFile );
    if ( fd->exec() == QDialog::Accepted )
    {
         QString t = fd->selectedFile();
         // mache was mit "t"
    }
    else
 return;
}

Verfasst: 10. Juni 2005 15:58
von dani.80
Ahja, ok.
Also bei mir öffnet sich ein normaler QFileDialog.
Hab gerade bei kwrite den Dialog ausprobiert, da funktioniert es auch mit der Mehrfachauswahl von Ordnern.
Ist das der Grund dass es nicht funktioniert? Aber wenn du sagst, unter Windows gehts auch, dann sollte es doch auch mit dem "normalen" QFileDialog funktionieren, oder nicht?

Klar schaffen wir das :)

Viele Grüße,
Dani

Verfasst: 10. Juni 2005 16:41
von ron
Sieh mal in Deinem EMail-Fach nach, dort ist die Beispiel-App.

Ja, mit normalem QFileDialog ist dies auch möglich, ich sagte ja schon, -
bei Win gehts ja auch !

ron :D

Re: Mehrfachauswahl über QFileDialog + Ordner rekursiv ausle

Verfasst: 10. Juni 2005 16:53
von ron
Ja Christian Du hast recht, das "" ist wohl noch ein Relikt aus meinen alten MFC-Zeiten.
Danke für den Tip.
Christian81 hat geschrieben:
ron hat geschrieben:

Code: Alles auswählen

...
	    // win-user benutzen nat. "\"
	    onAddFolders( fi->absFilePath() + "/" );
...
Oder noch besser, man nimmt die Qt-eigene Funktion char QDir::separator (). Des weiteren konvertiert Qt bei den Zugriffen auf die OS-spezifischen Dateifunktionen die Separatoren automatisch so das man im Grunde immer nur '/' zu nehmen braucht.

Verfasst: 22. Oktober 2005 19:28
von HaaseD
Versuche gerade obiges Beispiel in Qt4 umzusetzen und bin mit durch das Lesen der Dokumentation ein ganzes Stück vorangekommen. Einige Probleme sind aber noch beblieben.

Ich habe folgende Anpassungen bereits vorgenommen:

QFileDialog

Code: Alles auswählen

Qt3:	getOpenFileNames(filters, Qstring::null, this, 0, tr("Add") );
Qt4:	getOpenFileNames(this, tr("Add"), Qstring::null, filters );
QFileInfo():

Code: Alles auswählen

Qt3:	absFilePath()
Qt4:	absoluteFilePath();
QDir():

Code: Alles auswählen

Qt3:	setMatchAllDirs();
Qt4:	setFilter(QDir::AllDirs);
Die Fehlermeldungen danach lauten noch:

muster.cpp: In member function `void MusterForm::onAddFolders(QString)':
muster.cpp:84: error: `QFileInfoListIterator' undeclared (first use this function)
muster.cpp:84: error: (Each undeclared identifier is reported only once for each function it appears in.)
muster.cpp:84: error: expected `;' before "it"

Code: Alles auswählen

QFileInfoListIterator it( *list ); 
dies ist dann die Folge:

muster.cpp:87: error: `it' undeclared (first use this function)

muster.cpp: In member function `void MusterForm::onUpdateList()':
muster.cpp:111: error: `QListViewItem' undeclared (first use this function)
muster.cpp:111: error: `item' undeclared (first use this function)
muster.cpp:111: error: `QListViewItem' has not been declared

QListViewItem gibt es in Qt4 nicht mehr, daher habe ich es mit Q3ListViewItem probiert, was aber weitere Fehlermeldungen produziert.

Hoffe ihr könnt mir einen Denkanstoss geben.

MfG Dirk

Scheinbar vergebliche Liebesmüh

Verfasst: 22. Oktober 2005 22:29
von HaaseD
Nachdem ich die Ausgabe statt an ein QListView zu schicken an ein QTextEdit schicke und noch eine kleine Anpassung wegen QFileInfoListIterator gemacht habe, funktioniert das Progamm erstmal, nur will QFileDialog keine Verzeichnisse einlesen.

Die Qt4-Doc sagt dazu:
Under Windows and Mac OS X, this static function will use the native file dialog and not a QFileDialog.
Muss ich mich wohl nach einer anderen Lösung umsehen. :(

Gruss Dirk

Verfasst: 26. Mai 2006 02:05
von saubue
Hab auch mal ein bissl rumprobiert und hab folgende Funktion erstellt:

GLOBALS: QStringList *files (muss vor dem Aufruf initialisiert werden)

Code: Alles auswählen

void mainWidget::loopFolders(QString folder)
    QDir d(folder);
 
	if (!d.exists())
    {
		QMessageBox::information(this, "Error", "Can't open folder");
		return;
    }
   
	const QStringList list = d.entryList();
   
    for (long i = 0; i < list.size(); i++)
    {
		// Skip  "." and ".."
		if (list[i] == "." || list[i] == "..")
			continue;
		else if (QDir(folder + "/" + list[i]).exists())
			loopFolders(folder + "/" + list[i] + "/" );
		else if (QFileInfo(folder + "/" + list[i]).exists())
			files->append(list[i]);
    }
}

Verfasst: 5. Juni 2006 21:51
von HaaseD
DANKE! Damit klappt es jetzt auch unter Windows und ich kann an meinem Programm weiterarbeiten.