PDA

View Full Version : File browser



jp
17th July 2006, 06:31
I am using Qt4.1.4 under WinXp
I made a little File browser for didactical reasons and to override certain extensions Windows Explorer runs by default.
Everything works to the extent that I navigate directories and drives and launch programs the way I want but so far all attempts to incorporate a given typed content of LineEdit to the File browser have eluded me.
Could anyone be so kind to illuminate me with some pointers?


#include <QtGui>

//#include <QDebug>

class CListBox: public QListWidget {
Q_OBJECT
public:
CListBox(QWidget *pParent);
signals:
void currentDir(const QString&);
protected slots:
void onActivation(QListWidgetItem *item);
};

CListBox::CListBox(QWidget *pParent): QListWidget(pParent) {
clear();
QDir dir;
QStringList list;
QStringList arg = QCoreApplication::arguments();
if (arg.size() == 2) dir.setCurrent(arg.at(1));
dir.setFilter(QDir::AllEntries | QDir::Hidden | QDir::System);
dir.setSorting(QDir::DirsFirst | QDir::IgnoreCase | QDir::Name);
list = dir.entryList();
for (int i = 0; i < list.size(); ++i) {
insertItem(i, list.at(i));
}
dir = dir.canonicalPath();
if (dir.isRoot()) {
//QFileInfoList roots = QDir::drives();
QList<QFileInfo> roots = QDir::drives();
QString string = QDir::currentPath();
string.truncate(3);
int n = 0;
for (int i = 0; i < roots.size(); ++i) {
QFileInfo info = roots.at(i);
if (info.absoluteFilePath() != string) {
insertItem(n, info.absoluteFilePath());
++n;
}
}
} else takeItem(0);
connect(this, SIGNAL(itemActivated(QListWidgetItem*)), this, SLOT(onActivation(QListWidgetItem*)));
};

void CListBox::onActivation(QListWidgetItem *item) {
QDir dir;
int flag = 0;
QStringList list;
QString str = item->text();
QFileInfo fiche(str);
QString ext = fiche.suffix().toLower();
QStringList ext1, ext2;
ext1 << "" << "txt" << "bak" <<"bat" <<"ini" <<"log" << "dat" << "sys";
ext2 <<"h"<<"cpp"<<"pro"<<"lsp"<<"frm"<<"java"<<"vb"<<"bas"<<"js"<<"awk"<<"xul";
if (fiche.isDir()) {
clear();
dir.setCurrent(str);
emit currentDir(dir.currentPath());
dir.setFilter(QDir::AllEntries | QDir::Hidden | QDir::System);
dir.setSorting(QDir::DirsFirst | QDir::IgnoreCase | QDir::Name);
list = dir.entryList();
for (int i = 0; i < list.size(); ++i) {
insertItem(i, list.at(i));
}
dir = dir.canonicalPath();
if (dir.isRoot()) {
clear();
dir.setFilter(QDir::AllEntries | QDir::Hidden | QDir::System);
dir.setSorting(QDir::DirsFirst | QDir::IgnoreCase| QDir::Name);
list = dir.entryList();
for (int i = 0; i < list.size(); ++i) {
insertItem(i, list.at(i));
}
//QFileInfoList roots = QDir::drives();
QList<QFileInfo> roots = QDir::drives();
QString string = QDir::currentPath();
string.truncate(3);
int n = 0;
for (int i = 0; i < roots.size(); ++i) {
QFileInfo info = roots.at(i);
if (info.absoluteFilePath() != string) {
insertItem(n, info.absoluteFilePath());
++n;
}
}
} else takeItem(0);
} else {
emit currentDir(dir.currentPath());
QString cmd = "c:/dos/ed /p ";
if (ext1.contains(ext)) flag = 1;
if (ext2.contains(ext)) flag = 2;
switch(flag) {
case 1: QProcess::startDetached(cmd.append(str)); break;
case 2: QProcess::startDetached("led", QStringList() << str); break;
default: QProcess::startDetached("start", QStringList() << str);
}
}
};

// --------------------

class CLineEdit: public QLineEdit {
Q_OBJECT
public:
CLineEdit(QWidget *pParent);
signals:
void setDir(const QString&);
protected slots:
void onReturnPressed();
};

CLineEdit::CLineEdit(QWidget *pParent): QLineEdit(pParent) {
setText(QDir::currentPath());
connect( this, SIGNAL(returnPressed()), this, SLOT(onReturnPressed()));
};

void CLineEdit::onReturnPressed() {
QDir dir;
QString string = displayText();
dir.setCurrent(string);
emit setDir(dir.currentPath());
//qDebug() << QDir::currentPath();
};

// --------------------

int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QFrame wnd;
QVBoxLayout layout(&wnd);
CListBox lbox(&wnd);
CLineEdit ledit(&wnd);
layout.addWidget(&lbox, Qt::AlignHCenter | Qt::AlignVCenter);
layout.addWidget(&ledit, Qt::AlignHCenter | Qt::AlignVCenter);
wnd.setWindowTitle("File browser");
wnd.show();
lbox.setFocus();

QPalette p1 = lbox.palette();
p1.setColor(QPalette::Base, QColor(255, 248, 220));
lbox.setPalette(p1);
QPalette p2 = ledit.palette();
p2.setColor(QPalette::Base, QColor(255, 248, 220));
ledit.setPalette(p2);

QObject::connect(&lbox, SIGNAL(currentDir(const QString&)), &ledit, SLOT(setText(const QString&)));
QObject::connect(&ledit, SIGNAL(setDir(const QString&)), &lbox, SLOT(update()));

return app.exec();
}

#include "main.moc"


All codes packed together as a single file to make it synoptic!

jpn
17th July 2006, 09:11
Check this thread (http://www.qtcentre.org/forum/f-qt-programming-2/t-suggestionsideas-about-a-file-browser-1625.html) out. It could be useful. Using QDirModel + any QAbstractItemView descendant is rather simple.

For launching executables you might consider using an combination of:

bool QFileInfo::isExecutable (http://doc.trolltech.com/4.1/qfileinfo.html#isExecutable)() const
QProcess (http://doc.trolltech.com/4.1/qprocess)


For opening other than executable files:

There is no platform independant way in current version of Qt. You will have to use some platform specific blocks and ShellExecute() for windows and something corresponding for linux. As a hint, try searching this forum for "ShellExecute" and you might find something useful.
Something worth checking out is QDS's launcher service (http://qds.berlios.de/services.html#Launcher). Upcoming Qt 4.2 will have also some kind of desktop services (http://doc.trolltech.com/4.2/qdesktopservices.html).

jp
17th July 2006, 17:39
Actually the launching of files is not an issue by itself since the File browser acknowledges file extensions and acts accordingly. Also one can always put the explorer as the default switch case to take care of the non-filtered extensions and as you mentioned future Qt versions will not fail to act more discriminately.
What puzzles me the most is when one enters a path name in the LineEdit it becomes the new current directory and should trigger a rerun of the directory reading in the ListBox.
• QObject::connect(&ledit, SIGNAL(setDir(const QString&)), &lbox, SLOT(update()));
But the update is not taking place, should it be considered as bug?

jpn
17th July 2006, 17:52
What puzzle me the most is when one enters a path name in the LineEdit it becomes the new current directory and should trigger a rerun of the directory reading in the ListBox.
• QObject::connect(&ledit, SIGNAL(setDir(const QString&)), &lbox, SLOT(update()));
But the update is not taking place, should it be considered as bug?
That does only schedule a new paint event for the listbox. As the content hasn't changed anyhow, nothing happens. You haven't made the listbox to react anyhow. Maybe you should add a custom slot which takes the changed dir as a parameter and change the contents of the listbox?

jp
18th July 2006, 09:46
• QObject::connect(&ledit, SIGNAL(setDir(const QString&)), &lbox, SLOT(close()));

Even without dwelling too much into the semantic of what update is supposed to mean, the close command as expected triggers the ListBox to close down and equally for call to an update one will expect the ListBox to do an update with a rerun of its reading.

jpn
18th July 2006, 09:55
..and equally for call to an update one will expect the ListBox to do an update with a rerun of its reading.
It will redraw its contents. The contents just haven't magically changed to anything. You are only changing the listbox contents in constructor and when an item is activated. You are not changing the listbox contents when a paint event occurs.

jp
18th July 2006, 17:05
... You are only changing the listbox contents in constructor and when an item is activated. You are not changing the listbox contents when a paint event occurs.

OK then, if update is not updating and unless Qt is capable of faking events, Qt promises to be a fairly unwieldy scripting language!

Chicken Blood Machine
18th July 2006, 17:39
OK then, if update is not updating and unless Qt is capable of faking events, Qt promises to be a fairly unwieldy scripting language!

Hmmm, two things:
1. Qt is capable of faking certain events.
2. Qt is not a scripting language.

jpn
18th July 2006, 19:48
OK then, if update is not updating and unless Qt is capable of faking events, Qt promises to be a fairly unwieldy scripting language!
No offense, but the problem is not at all within Qt. The problem lies in your code structure. Let's make this clear. How do you expect the list box to change it's contents after calling update()? It will just redraw earlierly inserted items. You need to pass the current dir from the line edit to the list box and change the contents.

To make this work, your code should look more like this:



void CListBox::onActivation(QListWidgetItem *item)
{
setDir(item->text());
}

void CListBox::setDir(const QString& dir)
{
QFileInfo fiche(dir);
...
for (...)
insertItem(...)
...
emit dirChanged(dir);
}

void CLineEdit::onReturnPressed()
{
emit dirChanged(text());
}

QObject::connect(&lbox, SIGNAL(dirChanged(const QString&)), &ledit, SLOT(setText(const QString&)));
QObject::connect(&ledit, SIGNAL(dirChanged(const QString&)), &lbox, SLOT(setDir(const QString&)));

jp
19th July 2006, 02:46
Thanks jpn and Chicken Blood Machine.
I was simply under the misguided impression that one could write compact code without the benefit of using the QDirModel class.