-rw-r--r-- | library/fileselector.cpp | 470 |
1 files changed, 340 insertions, 130 deletions
diff --git a/library/fileselector.cpp b/library/fileselector.cpp index 013f43a..382012f 100644 --- a/library/fileselector.cpp +++ b/library/fileselector.cpp | |||
@@ -1,12 +1,12 @@ | |||
1 | /********************************************************************** | 1 | /********************************************************************** |
2 | ** Copyright (C) 2000 Trolltech AS. All rights reserved. | 2 | ** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. |
3 | ** | 3 | ** |
4 | ** This file is part of Qtopia Environment. | 4 | ** This file is part of the Qtopia Environment. |
5 | ** | 5 | ** |
6 | ** This file may be distributed and/or modified under the terms of the | 6 | ** This file may be distributed and/or modified under the terms of the |
7 | ** GNU General Public License version 2 as published by the Free Software | 7 | ** GNU General Public License version 2 as published by the Free Software |
8 | ** Foundation and appearing in the file LICENSE.GPL included in the | 8 | ** Foundation and appearing in the file LICENSE.GPL included in the |
9 | ** packaging of this file. | 9 | ** packaging of this file. |
10 | ** | 10 | ** |
11 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE | 11 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE |
12 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | 12 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
@@ -25,329 +25,539 @@ | |||
25 | #include "fileselector.h" | 25 | #include "fileselector.h" |
26 | #include "fileselector_p.h" | 26 | #include "fileselector_p.h" |
27 | #include "global.h" | 27 | #include "global.h" |
28 | #include "resource.h" | 28 | #include "resource.h" |
29 | #include "config.h" | 29 | #include "config.h" |
30 | #include "applnk.h" | 30 | #include "applnk.h" |
31 | #include "storage.h" | 31 | #include "storage.h" |
32 | #include "qpemenubar.h" | 32 | #include "qpemenubar.h" |
33 | #ifdef QWS | ||
33 | #include "qcopchannel_qws.h" | 34 | #include "qcopchannel_qws.h" |
35 | #endif | ||
34 | #include "lnkproperties.h" | 36 | #include "lnkproperties.h" |
35 | #include "applnk.h" | 37 | #include "applnk.h" |
36 | #include "qpeapplication.h" | 38 | #include "qpeapplication.h" |
37 | #include "categorymenu.h" | 39 | #include "categorymenu.h" |
40 | #include "categoryselect.h" | ||
41 | #include "mimetype.h" | ||
42 | #include "categories.h" | ||
38 | 43 | ||
39 | #include <stdlib.h> | 44 | #include <stdlib.h> |
40 | 45 | ||
41 | #include <qdir.h> | 46 | #include <qdir.h> |
42 | #include <qwidget.h> | 47 | #include <qwidget.h> |
43 | #include <qpopupmenu.h> | 48 | #include <qpopupmenu.h> |
44 | #include <qtoolbutton.h> | 49 | #include <qtoolbutton.h> |
45 | #include <qpushbutton.h> | 50 | #include <qpushbutton.h> |
46 | #include <qheader.h> | 51 | #include <qheader.h> |
47 | #include <qtooltip.h> | 52 | #include <qtooltip.h> |
53 | #include <qwhatsthis.h> | ||
48 | 54 | ||
55 | class TypeCombo : public QComboBox | ||
56 | { | ||
57 | Q_OBJECT | ||
58 | public: | ||
59 | TypeCombo( QWidget *parent, const char *name=0 ) | ||
60 | : QComboBox( parent, name ) | ||
61 | { | ||
62 | connect( this, SIGNAL(activated(int)), this, SLOT(selectType(int)) ); | ||
63 | } | ||
64 | |||
65 | void reread( DocLnkSet &files, const QString &filter ); | ||
66 | |||
67 | signals: | ||
68 | void selected( const QString & ); | ||
69 | |||
70 | protected slots: | ||
71 | void selectType( int idx ) { | ||
72 | emit selected( typelist[idx] ); | ||
73 | } | ||
74 | |||
75 | protected: | ||
76 | QStringList typelist; | ||
77 | QString prev; | ||
78 | }; | ||
79 | |||
80 | void TypeCombo::reread( DocLnkSet &files, const QString &filter ) | ||
81 | { | ||
82 | typelist.clear(); | ||
83 | QStringList filters = QStringList::split( ';', filter ); | ||
84 | int pos = filter.find( '/' ); | ||
85 | //### do for each filter | ||
86 | if ( filters.count() == 1 && pos >= 0 && filter[pos+1] != '*' ) { | ||
87 | typelist.append( filter ); | ||
88 | clear(); | ||
89 | QString minor = filter.mid( pos+1 ); | ||
90 | minor[0] = minor[0].upper(); | ||
91 | insertItem( tr("%1 files").arg(minor) ); | ||
92 | setCurrentItem(0); | ||
93 | setEnabled( FALSE ); | ||
94 | return; | ||
95 | } | ||
96 | |||
97 | QListIterator<DocLnk> dit( files.children() ); | ||
98 | for ( ; dit.current(); ++dit ) { | ||
99 | if ( !typelist.contains( (*dit)->type() ) ) | ||
100 | typelist.append( (*dit)->type() ); | ||
101 | } | ||
102 | |||
103 | QStringList types; | ||
104 | QStringList::ConstIterator it; | ||
105 | for (it = typelist.begin(); it!=typelist.end(); ++it) { | ||
106 | QString t = *it; | ||
107 | if ( t.left(12) == "application/" ) { | ||
108 | MimeType mt(t); | ||
109 | const AppLnk* app = mt.application(); | ||
110 | if ( app ) | ||
111 | t = app->name(); | ||
112 | else | ||
113 | t = t.mid(12); | ||
114 | } else { | ||
115 | QString major, minor; | ||
116 | int pos = t.find( '/' ); | ||
117 | if ( pos >= 0 ) { | ||
118 | major = t.left( pos ); | ||
119 | minor = t.mid( pos+1 ); | ||
120 | } | ||
121 | if ( minor.find( "x-" ) == 0 ) | ||
122 | minor = minor.mid( 2 ); | ||
123 | minor[0] = minor[0].upper(); | ||
124 | major[0] = major[0].upper(); | ||
125 | if ( filters.count() > 1 ) | ||
126 | t = tr("%1 %2", "minor mimetype / major mimetype").arg(minor).arg(major); | ||
127 | else | ||
128 | t = minor; | ||
129 | } | ||
130 | types += tr("%1 files").arg(t); | ||
131 | } | ||
132 | for (it = filters.begin(); it!=filters.end(); ++it) { | ||
133 | typelist.append( *it ); | ||
134 | int pos = (*it).find( '/' ); | ||
135 | if ( pos >= 0 ) { | ||
136 | QString maj = (*it).left( pos ); | ||
137 | maj[0] = maj[0].upper(); | ||
138 | types << tr("All %1 files").arg(maj); | ||
139 | } | ||
140 | } | ||
141 | if ( filters.count() > 1 ) { | ||
142 | typelist.append( filter ); | ||
143 | types << tr("All files"); | ||
144 | } | ||
145 | prev = currentText(); | ||
146 | clear(); | ||
147 | insertStringList(types); | ||
148 | for (int i=0; i<count(); i++) { | ||
149 | if ( text(i) == prev ) { | ||
150 | setCurrentItem(i); | ||
151 | break; | ||
152 | } | ||
153 | } | ||
154 | if ( prev.isNull() ) | ||
155 | setCurrentItem(count()-1); | ||
156 | setEnabled( TRUE ); | ||
157 | } | ||
158 | |||
159 | |||
160 | //=========================================================================== | ||
49 | 161 | ||
50 | FileSelectorItem::FileSelectorItem( QListView *parent, const DocLnk &f ) | 162 | FileSelectorItem::FileSelectorItem( QListView *parent, const DocLnk &f ) |
51 | : QListViewItem( parent ), fl( f ) | 163 | : QListViewItem( parent ), fl( f ) |
52 | { | 164 | { |
53 | setText( 0, f.name() ); | 165 | setText( 0, f.name() ); |
54 | setPixmap( 0, f.pixmap() ); | 166 | setPixmap( 0, f.pixmap() ); |
55 | } | 167 | } |
56 | 168 | ||
57 | FileSelectorItem::~FileSelectorItem() | 169 | FileSelectorItem::~FileSelectorItem() |
58 | { | 170 | { |
59 | } | 171 | } |
60 | 172 | ||
61 | class FileSelectorViewPrivate | 173 | FileSelectorView::FileSelectorView( QWidget *parent, const char *name ) |
62 | { | 174 | : QListView( parent, name ) |
63 | public: | ||
64 | CategoryMenu *cm; | ||
65 | bool m_noItems:1; | ||
66 | }; | ||
67 | |||
68 | FileSelectorView::FileSelectorView( const QString &f, QWidget *parent, const char *name ) | ||
69 | : QListView( parent, name ), filter( f ), count( 0 ) | ||
70 | { | 175 | { |
71 | d = new FileSelectorViewPrivate(); | ||
72 | d->cm = 0; | ||
73 | d->m_noItems = false; | ||
74 | setAllColumnsShowFocus( TRUE ); | 176 | setAllColumnsShowFocus( TRUE ); |
75 | addColumn( tr( "Name" ) ); | 177 | addColumn( tr( "Name" ) ); |
76 | header()->hide(); | 178 | header()->hide(); |
77 | |||
78 | fileManager = new FileManager; | ||
79 | reread(); | ||
80 | QCopChannel *channel = new QCopChannel( "QPE/Card", this ); | ||
81 | connect( channel, SIGNAL(received(const QCString &, const QByteArray &)), | ||
82 | this, SLOT(cardMessage( const QCString &, const QByteArray &)) ); | ||
83 | } | 179 | } |
84 | 180 | ||
85 | FileSelectorView::~FileSelectorView() | 181 | FileSelectorView::~FileSelectorView() |
86 | { | 182 | { |
87 | } | 183 | } |
88 | 184 | ||
89 | void FileSelectorView::reread() | ||
90 | { | ||
91 | QString oldFile; | ||
92 | FileSelectorItem *item; | ||
93 | if( !d->m_noItems ) { // there are items | ||
94 | item = (FileSelectorItem *)selectedItem(); | ||
95 | if ( item ) | ||
96 | oldFile = item->file().file(); | ||
97 | } | ||
98 | clear(); | ||
99 | DocLnkSet files; | ||
100 | Global::findDocuments(&files, filter); | ||
101 | count = files.children().count(); | ||
102 | if(count == 0 ){ // No Documents | ||
103 | d->m_noItems = true; | ||
104 | QListViewItem *it = new QListViewItem(this, tr("There are no files in this directory." ), "empty" ); | ||
105 | it->setSelectable(FALSE ); | ||
106 | return; | ||
107 | } | ||
108 | QListIterator<DocLnk> dit( files.children() ); | ||
109 | for ( ; dit.current(); ++dit ) { | ||
110 | if (d->cm) | ||
111 | if (!d->cm->isSelected((**dit).categories())) | ||
112 | continue; | ||
113 | item = new FileSelectorItem( this, **dit ); | ||
114 | if ( item->file().file() == oldFile ) | ||
115 | setCurrentItem( item ); | ||
116 | } | ||
117 | if ( !selectedItem() ) | ||
118 | setCurrentItem( firstChild() ); | ||
119 | } | ||
120 | |||
121 | void FileSelectorView::setCategoryFilter(CategoryMenu *cm) | ||
122 | { | ||
123 | d->cm = cm; | ||
124 | connect(cm, SIGNAL(categoryChange()), this, SLOT(categoryChanged()) ); | ||
125 | } | ||
126 | |||
127 | void FileSelectorView::categoryChanged() { reread(); } | ||
128 | |||
129 | void FileSelectorView::cardMessage( const QCString &msg, const QByteArray &) | ||
130 | { | ||
131 | if ( msg == "mtabChanged()" ) | ||
132 | reread(); | ||
133 | } | ||
134 | |||
135 | void FileSelectorView::keyPressEvent( QKeyEvent *e ) | 185 | void FileSelectorView::keyPressEvent( QKeyEvent *e ) |
136 | { | 186 | { |
137 | QString txt = e->text(); | 187 | QString txt = e->text(); |
138 | if (e->key() == Key_Space) | 188 | if (e->key() == Key_Space) |
139 | emit returnPressed( currentItem() ); | 189 | emit returnPressed( currentItem() ); |
140 | else if ( !txt.isNull() && txt[0] > ' ' && e->key() < 0x1000 ) | 190 | else if ( !txt.isNull() && txt[0] > ' ' && e->key() < 0x1000 ) |
141 | e->ignore(); | 191 | e->ignore(); |
142 | else | 192 | else |
143 | QListView::keyPressEvent(e); | 193 | QListView::keyPressEvent(e); |
144 | } | 194 | } |
145 | 195 | ||
196 | class NewDocItem : public FileSelectorItem | ||
197 | { | ||
198 | public: | ||
199 | NewDocItem( QListView *parent, const DocLnk &f ) | ||
200 | : FileSelectorItem( parent, f ) { | ||
201 | setText( 0, QObject::tr("New Document") ); | ||
202 | QImage img( Resource::loadImage( "new" ) ); | ||
203 | QPixmap pm; | ||
204 | pm = img.smoothScale( AppLnk::smallIconSize(), AppLnk::smallIconSize() ); | ||
205 | setPixmap( 0, pm ); | ||
206 | } | ||
207 | QString key ( int, bool ) const { | ||
208 | return QString("\n"); | ||
209 | } | ||
210 | |||
211 | void paintCell( QPainter *p, const QColorGroup &cg, int column, int width, int alignment ) { | ||
212 | QFont oldFont = p->font(); | ||
213 | QFont newFont = p->font(); | ||
214 | newFont.setWeight( QFont::Bold ); | ||
215 | p->setFont( newFont ); | ||
216 | FileSelectorItem::paintCell( p, cg, column, width, alignment ); | ||
217 | p->setFont( oldFont ); | ||
218 | } | ||
219 | |||
220 | int width( const QFontMetrics &fm, const QListView *v, int c ) const { | ||
221 | return FileSelectorItem::width( fm, v, c )*4/3; // allow for bold font | ||
222 | } | ||
223 | }; | ||
224 | |||
225 | //=========================================================================== | ||
226 | |||
146 | class FileSelectorPrivate | 227 | class FileSelectorPrivate |
147 | { | 228 | { |
148 | public: | 229 | public: |
149 | CategoryMenu *cm; | 230 | TypeCombo *typeCombo; |
150 | QMenuBar *mb; | 231 | CategorySelect *catSelect; |
232 | QValueList<QRegExp> mimeFilters; | ||
233 | int catId; | ||
234 | bool showNew; | ||
235 | NewDocItem *newDocItem; | ||
236 | DocLnkSet files; | ||
237 | QHBox *toolbar; | ||
151 | }; | 238 | }; |
152 | 239 | ||
153 | /*! | 240 | /*! |
154 | \class FileSelector fileselector.h | 241 | \class FileSelector fileselector.h |
155 | \brief The FileSelector widget allows the user to select DocLnk objects. | 242 | \brief The FileSelector widget allows the user to select DocLnk objects. |
243 | |||
244 | This class presents a file selection dialog to the user. This widget | ||
245 | is usually the first widget seen in a \link docwidget.html | ||
246 | document-oriented application\endlink. The developer will most often | ||
247 | create this widget in combination with a <a | ||
248 | href="../qt/qwidgetstack.html"> QWidgetStack</a> and the appropriate | ||
249 | editor and/or viewer widget for their application. This widget | ||
250 | should be shown first and the user can the select which document | ||
251 | they wish to operate on. Please refer to the implementation of | ||
252 | texteditor for an example of how to tie these classes together. | ||
253 | |||
254 | Use setNewVisible() depending on whether the application can be used | ||
255 | to create new files or not. Use setCloseVisible() depending on | ||
256 | whether the user may leave the dialog without creating or selecting | ||
257 | a document or not. The number of files in the view is available from | ||
258 | fileCount(). To force the view to be updated call reread(). | ||
259 | |||
260 | If the user presses the 'New Document' button the newSelected() | ||
261 | signal is emitted. If the user selects an existing file the | ||
262 | fileSelected() signal is emitted. The selected file's \link | ||
263 | doclnk.html DocLnk\endlink is available from the selected() | ||
264 | function. If the file selector is no longer necessary the closeMe() | ||
265 | signal is emitted. | ||
266 | |||
267 | \ingroup qtopiaemb | ||
268 | \sa FileManager | ||
156 | */ | 269 | */ |
157 | 270 | ||
158 | /*! | 271 | /*! |
159 | Constructs a FileSelector with mime filter \a f. | 272 | Constructs a FileSelector with mime filter \a f. |
160 | The standard Qt \a parent and \a name parameters are passed to the | 273 | The standard Qt \a parent and \a name parameters are passed to the |
161 | parent. | 274 | parent widget. |
162 | 275 | ||
163 | If \a newVisible is TRUE, the widget has an button allowing the user | 276 | If \a newVisible is TRUE, the widget has a button to allow the user |
164 | the create "new" documents - editor applications will have this while | 277 | the create "new" documents; this is useful for applications that can |
165 | viewer applications will not. | 278 | create and edit documents but not suitable for applications that |
279 | only provide viewing. | ||
166 | 280 | ||
167 | If \a closeVisible is TRUE, the widget has an button allowinf the user | 281 | \a closeVisible is deprecated |
168 | to select "no document". | ||
169 | 282 | ||
170 | \sa DocLnkSet::DocLnkSet() | 283 | \sa DocLnkSet::DocLnkSet() |
171 | */ | 284 | */ |
172 | FileSelector::FileSelector( const QString &f, QWidget *parent, const char *name, bool newVisible, bool closeVisible ) | 285 | FileSelector::FileSelector( const QString &f, QWidget *parent, const char *name, bool newVisible, bool closeVisible ) |
173 | : QVBox( parent, name ), filter( f ) | 286 | : QVBox( parent, name ), filter( f ) |
174 | { | 287 | { |
175 | setMargin( 0 ); | 288 | setMargin( 0 ); |
176 | setSpacing( 0 ); | 289 | setSpacing( 0 ); |
177 | QHBox *top = new QHBox( this ); | ||
178 | top->setBackgroundMode( PaletteButton );// same colour as toolbars | ||
179 | top->setSpacing( 0 ); | ||
180 | |||
181 | QWidget *spacer = new QWidget( top ); | ||
182 | spacer->setBackgroundMode( PaletteButton ); | ||
183 | 290 | ||
184 | d = new FileSelectorPrivate(); | 291 | d = new FileSelectorPrivate(); |
185 | d->mb = new QMenuBar(spacer); | 292 | d->newDocItem = 0; |
186 | d->cm = new CategoryMenu("Document View", this); | 293 | d->showNew = newVisible; |
187 | QPEMenuToolFocusManager::manager()->addWidget( d->mb ); | 294 | d->catId = -2; // All files |
188 | d->mb->insertItem(tr("View"), d->cm); | ||
189 | 295 | ||
296 | d->toolbar = new QHBox( this ); | ||
297 | d->toolbar->setBackgroundMode( PaletteButton ); // same colour as toolbars | ||
298 | d->toolbar->setSpacing( 0 ); | ||
299 | d->toolbar->hide(); | ||
190 | 300 | ||
191 | QToolButton *tb = new QToolButton( top ); | 301 | QWidget *spacer = new QWidget( d->toolbar ); |
192 | tb->setPixmap( Resource::loadPixmap( "new" ) ); | 302 | spacer->setBackgroundMode( PaletteButton ); |
193 | connect( tb, SIGNAL( clicked() ), this, SLOT( createNew() ) ); | ||
194 | buttonNew = tb; | ||
195 | tb->setFixedSize( 18, 20 ); // tb->sizeHint() ); | ||
196 | tb->setAutoRaise( TRUE ); | ||
197 | QToolTip::add( tb, tr( "Create a new Document" ) ); | ||
198 | QPEMenuToolFocusManager::manager()->addWidget( tb ); | ||
199 | 303 | ||
200 | tb = new QToolButton( top ); | 304 | QToolButton *tb = new QToolButton( d->toolbar ); |
201 | tb->setPixmap( Resource::loadPixmap( "close" ) ); | 305 | tb->setPixmap( Resource::loadPixmap( "close" ) ); |
202 | connect( tb, SIGNAL( clicked() ), this, SIGNAL( closeMe() ) ); | 306 | connect( tb, SIGNAL( clicked() ), this, SIGNAL( closeMe() ) ); |
203 | buttonClose = tb; | 307 | buttonClose = tb; |
204 | tb->setFixedSize( 18, 20 ); // tb->sizeHint() ); | 308 | tb->setFixedSize( 18, 20 ); // tb->sizeHint() ); |
205 | tb->setAutoRaise( TRUE ); | 309 | tb->setAutoRaise( TRUE ); |
206 | QToolTip::add( tb, tr( "Close the File Selector" ) ); | 310 | QToolTip::add( tb, tr( "Close the File Selector" ) ); |
207 | QPEMenuToolFocusManager::manager()->addWidget( tb ); | 311 | QPEMenuToolFocusManager::manager()->addWidget( tb ); |
208 | 312 | ||
209 | view = new FileSelectorView( filter, this, "fileview" ); | 313 | view = new FileSelectorView( this, "fileview" ); |
210 | view->setCategoryFilter(d->cm); | ||
211 | QPEApplication::setStylusOperation( view->viewport(), QPEApplication::RightOnHold ); | 314 | QPEApplication::setStylusOperation( view->viewport(), QPEApplication::RightOnHold ); |
212 | connect( view, SIGNAL( mouseButtonClicked( int, QListViewItem *, const QPoint &, int ) ), | 315 | connect( view, SIGNAL( mouseButtonClicked( int, QListViewItem *, const QPoint &, int ) ), |
213 | this, SLOT( fileClicked( int, QListViewItem *, const QPoint &, int ) ) ); | 316 | this, SLOT( fileClicked( int, QListViewItem *, const QPoint &, int ) ) ); |
214 | connect( view, SIGNAL( mouseButtonPressed( int, QListViewItem *, const QPoint &, int ) ), | 317 | connect( view, SIGNAL( mouseButtonPressed( int, QListViewItem *, const QPoint &, int ) ), |
215 | this, SLOT( filePressed( int, QListViewItem *, const QPoint &, int ) ) ); | 318 | this, SLOT( filePressed( int, QListViewItem *, const QPoint &, int ) ) ); |
216 | connect( view, SIGNAL( returnPressed( QListViewItem * ) ), | 319 | connect( view, SIGNAL( returnPressed( QListViewItem * ) ), |
217 | this, SLOT( fileClicked( QListViewItem * ) ) ); | 320 | this, SLOT( fileClicked( QListViewItem * ) ) ); |
218 | 321 | ||
219 | setNewVisible( newVisible ); | 322 | QHBox *hb = new QHBox( this ); |
323 | d->typeCombo = new TypeCombo( hb ); | ||
324 | connect( d->typeCombo, SIGNAL(selected(const QString&)), | ||
325 | this, SLOT(typeSelected(const QString&)) ); | ||
326 | QWhatsThis::add( d->typeCombo, tr("Show documents of this type") ); | ||
327 | |||
328 | Categories c; | ||
329 | c.load(categoryFileName()); | ||
330 | QArray<int> vl( 0 ); | ||
331 | d->catSelect = new CategorySelect( hb ); | ||
332 | d->catSelect->setRemoveCategoryEdit( TRUE ); | ||
333 | d->catSelect->setCategories( vl, "Document View", tr("Document View") ); | ||
334 | d->catSelect->setAllCategories( TRUE ); | ||
335 | connect( d->catSelect, SIGNAL(signalSelected(int)), this, SLOT(catSelected(int)) ); | ||
336 | QWhatsThis::add( d->catSelect, tr("Show documents in this category") ); | ||
337 | |||
220 | setCloseVisible( closeVisible ); | 338 | setCloseVisible( closeVisible ); |
339 | |||
340 | QCopChannel *channel = new QCopChannel( "QPE/Card", this ); | ||
341 | connect( channel, SIGNAL(received(const QCString &, const QByteArray &)), | ||
342 | this, SLOT(cardMessage( const QCString &, const QByteArray &)) ); | ||
343 | |||
344 | reread(); | ||
345 | updateWhatsThis(); | ||
221 | } | 346 | } |
222 | 347 | ||
223 | /*! | 348 | /*! |
224 | Destroys the widget. | 349 | Destroys the widget. |
225 | */ | 350 | */ |
226 | FileSelector::~FileSelector() | 351 | FileSelector::~FileSelector() |
227 | { | 352 | { |
228 | 353 | delete d; | |
229 | } | 354 | } |
230 | 355 | ||
231 | /*! | 356 | /*! |
232 | Returns the number of files in the view. If this is zero, and editor | 357 | Returns the number of files in the view. If this is zero, an editor |
233 | application might avoid using the selector and immediately start with | 358 | application might bypass the selector and immediately start with |
234 | a "new" document. | 359 | a "new" document. |
235 | */ | 360 | */ |
236 | int FileSelector::fileCount() | 361 | int FileSelector::fileCount() |
237 | { | 362 | { |
238 | return view->fileCount(); | 363 | return d->files.children().count();; |
239 | } | 364 | } |
240 | 365 | ||
241 | /*! | 366 | /*! |
242 | Causes the file selector to act as if the "new" button was chosen. | 367 | Calling this function is the programmatic equivalent of the user |
368 | pressing the "new" button. | ||
243 | 369 | ||
244 | \sa newSelected(), closeMe() | 370 | \sa newSelected(), closeMe() |
245 | */ | 371 | */ |
246 | void FileSelector::createNew() | 372 | void FileSelector::createNew() |
247 | { | 373 | { |
248 | DocLnk f; | 374 | DocLnk f; |
249 | emit newSelected( f ); | 375 | emit newSelected( f ); |
250 | emit closeMe(); | 376 | emit closeMe(); |
251 | } | 377 | } |
252 | 378 | ||
253 | void FileSelector::fileClicked( int button, QListViewItem *i, const QPoint &, int ) | 379 | void FileSelector::fileClicked( int button, QListViewItem *i, const QPoint &, int ) |
254 | { | 380 | { |
255 | if ( !i ) | 381 | if ( !i ) |
256 | return; | 382 | return; |
257 | if(i->text(1) == QString::fromLatin1("empty" ) ) | ||
258 | return; | ||
259 | |||
260 | if ( button == Qt::LeftButton ) { | 383 | if ( button == Qt::LeftButton ) { |
261 | fileClicked( i ); | 384 | fileClicked( i ); |
262 | } | 385 | } |
263 | } | 386 | } |
264 | 387 | ||
265 | void FileSelector::filePressed( int button, QListViewItem *i, const QPoint &, int ) | 388 | void FileSelector::filePressed( int button, QListViewItem *i, const QPoint &, int ) |
266 | { | 389 | { |
267 | if ( !i ) | 390 | if ( !i || i == d->newDocItem ) |
268 | return; | 391 | return; |
269 | if(i->text(1) == QString::fromLatin1("empty" ) ) | ||
270 | return; | ||
271 | |||
272 | if ( button == Qt::RightButton ) { | 392 | if ( button == Qt::RightButton ) { |
273 | DocLnk l = ((FileSelectorItem *)i)->file(); | 393 | DocLnk l = ((FileSelectorItem *)i)->file(); |
274 | LnkProperties prop( &l ); | 394 | LnkProperties prop( &l ); |
275 | prop.showMaximized(); | 395 | prop.showMaximized(); |
276 | prop.exec(); | 396 | prop.exec(); |
277 | d->cm->reload(); | ||
278 | reread(); | 397 | reread(); |
279 | } | 398 | } |
280 | } | 399 | } |
281 | 400 | ||
282 | void FileSelector::fileClicked( QListViewItem *i ) | 401 | void FileSelector::fileClicked( QListViewItem *i ) |
283 | { | 402 | { |
284 | if ( !i ) | 403 | if ( !i ) |
285 | return; | 404 | return; |
286 | emit fileSelected( ( (FileSelectorItem*)i )->file() ); | 405 | if ( i == d->newDocItem ) { |
287 | emit closeMe(); | 406 | createNew(); |
407 | } else { | ||
408 | emit fileSelected( ( (FileSelectorItem*)i )->file() ); | ||
409 | emit closeMe(); | ||
410 | } | ||
411 | } | ||
412 | |||
413 | void FileSelector::typeSelected( const QString &type ) | ||
414 | { | ||
415 | d->mimeFilters.clear(); | ||
416 | QStringList subFilter = QStringList::split(";", type); | ||
417 | for( QStringList::Iterator it = subFilter.begin(); it != subFilter.end(); ++it ) | ||
418 | d->mimeFilters.append( QRegExp(*it, FALSE, TRUE) ); | ||
419 | updateView(); | ||
288 | } | 420 | } |
289 | 421 | ||
422 | void FileSelector::catSelected( int c ) | ||
423 | { | ||
424 | d->catId = c; | ||
425 | updateView(); | ||
426 | } | ||
427 | |||
428 | void FileSelector::cardMessage( const QCString &msg, const QByteArray &) | ||
429 | { | ||
430 | if ( msg == "mtabChanged()" ) | ||
431 | reread(); | ||
432 | } | ||
433 | |||
434 | |||
290 | /*! | 435 | /*! |
291 | Returns the selected DocLnk. The caller is responsible for deleting | 436 | Returns the selected \link doclnk.html DocLnk\endlink. The caller is |
292 | the returned value. | 437 | responsible for deleting the returned value. |
293 | */ | 438 | */ |
294 | const DocLnk *FileSelector::selected() | 439 | const DocLnk *FileSelector::selected() |
295 | { | 440 | { |
296 | FileSelectorItem *item = (FileSelectorItem *)view->selectedItem(); | 441 | FileSelectorItem *item = (FileSelectorItem *)view->selectedItem(); |
297 | if ( item ) | 442 | if ( item && item != d->newDocItem ) |
298 | return new DocLnk( item->file() ); | 443 | return new DocLnk( item->file() ); |
299 | return NULL; | 444 | return NULL; |
300 | } | 445 | } |
301 | 446 | ||
302 | /*! | 447 | /*! |
303 | \fn void FileSelector::fileSelected( const DocLnk &f ) | 448 | \fn void FileSelector::fileSelected( const DocLnk &f ) |
304 | 449 | ||
305 | This signal is emitted when the user selects a file. | 450 | This signal is emitted when the user selects a document. |
306 | \a f is the file. | 451 | \a f is the document. |
307 | */ | 452 | */ |
308 | 453 | ||
309 | /*! | 454 | /*! |
310 | \fn void FileSelector::newSelected( const DocLnk &f ) | 455 | \fn void FileSelector::newSelected( const DocLnk &f ) |
311 | 456 | ||
312 | This signal is emitted when the user selects "new" file. | 457 | This signal is emitted when the user selects a "new" document. |
313 | \a f is a DocLnk for the file. You will need to set the type | 458 | \a f is a DocLnk for the document. You will need to set the type |
314 | of the value after copying it. | 459 | of the document after copying it. |
315 | */ | 460 | */ |
316 | 461 | ||
317 | /*! | 462 | /*! |
318 | \fn void FileSelector::closeMe() | 463 | \fn void FileSelector::closeMe() |
319 | 464 | ||
320 | This signal is emitted when the user no longer needs to view the widget. | 465 | This signal is emitted when the user no longer needs to view the widget. |
321 | */ | 466 | */ |
322 | 467 | ||
323 | 468 | ||
324 | /*! | 469 | /*! |
325 | Sets whether a "new document" button is visible, according to \a b. | 470 | If \a b is TRUE a "new document" entry is visible; if \a b is FALSE |
471 | this entry is not visible and the user is unable to create new | ||
472 | documents from the dialog. | ||
326 | */ | 473 | */ |
327 | void FileSelector::setNewVisible( bool b ) | 474 | void FileSelector::setNewVisible( bool b ) |
328 | { | 475 | { |
329 | if ( b ) | 476 | if ( d->showNew != b ) { |
330 | buttonNew->show(); | 477 | d->showNew = b; |
331 | else | 478 | updateView(); |
332 | buttonNew->hide(); | 479 | updateWhatsThis(); |
480 | } | ||
333 | } | 481 | } |
334 | 482 | ||
335 | /*! | 483 | /*! |
336 | Sets whether a "no document" button is visible, according to \a b. | 484 | If \a b is TRUE a "close" or "no document" button is visible; if \a |
485 | b is FALSE this button is not visible and the user is unable to | ||
486 | leave the dialog without creating or selecting a document. | ||
487 | |||
488 | This function is deprecated. | ||
337 | */ | 489 | */ |
338 | void FileSelector::setCloseVisible( bool b ) | 490 | void FileSelector::setCloseVisible( bool b ) |
339 | { | 491 | { |
340 | if ( b ) | 492 | if ( b ) |
341 | buttonClose->show(); | 493 | d->toolbar->show(); |
342 | else | 494 | else |
343 | buttonClose->hide(); | 495 | d->toolbar->hide(); |
344 | } | 496 | } |
345 | 497 | ||
346 | /*! | 498 | /*! |
347 | Rereads the list of files. | 499 | Rereads the list of documents. |
348 | */ | 500 | */ |
349 | void FileSelector::reread() | 501 | void FileSelector::reread() |
350 | { | 502 | { |
351 | view->reread(); | 503 | d->files.clear(); |
504 | Global::findDocuments(&d->files, filter); | ||
505 | d->typeCombo->reread( d->files, filter ); | ||
506 | updateView(); | ||
352 | } | 507 | } |
353 | 508 | ||
509 | void FileSelector::updateView() | ||
510 | { | ||
511 | FileSelectorItem *item = (FileSelectorItem *)view->selectedItem(); | ||
512 | if ( item == d->newDocItem ) | ||
513 | item = 0; | ||
514 | QString oldFile; | ||
515 | if ( item ) | ||
516 | oldFile = item->file().file(); | ||
517 | view->clear(); | ||
518 | QListIterator<DocLnk> dit( d->files.children() ); | ||
519 | for ( ; dit.current(); ++dit ) { | ||
520 | bool mimeMatch = FALSE; | ||
521 | if ( d->mimeFilters.count() ) { | ||
522 | QValueList<QRegExp>::Iterator it; | ||
523 | for ( it = d->mimeFilters.begin(); it != d->mimeFilters.end(); ++it ) { | ||
524 | if ( (*it).match((*dit)->type()) >= 0 ) { | ||
525 | mimeMatch = TRUE; | ||
526 | break; | ||
527 | } | ||
528 | } | ||
529 | } else { | ||
530 | mimeMatch = TRUE; | ||
531 | } | ||
532 | if ( mimeMatch && | ||
533 | (d->catId == -2 || (*dit)->categories().contains(d->catId) || | ||
534 | (d->catId == -1 && (*dit)->categories().isEmpty())) ) { | ||
535 | item = new FileSelectorItem( view, **dit ); | ||
536 | if ( item->file().file() == oldFile ) | ||
537 | view->setCurrentItem( item ); | ||
538 | } | ||
539 | } | ||
540 | |||
541 | if ( d->showNew ) | ||
542 | d->newDocItem = new NewDocItem( view, DocLnk() ); | ||
543 | else | ||
544 | d->newDocItem = 0; | ||
545 | |||
546 | if ( !view->selectedItem() || view->childCount() == 1 ) { | ||
547 | view->setCurrentItem( view->firstChild() ); | ||
548 | view->setSelected( view->firstChild(), TRUE ); | ||
549 | } | ||
550 | } | ||
551 | |||
552 | void FileSelector::updateWhatsThis() | ||
553 | { | ||
554 | QWhatsThis::remove( this ); | ||
555 | QString text = tr("Click to select a document from the list"); | ||
556 | if ( d->showNew ) | ||
557 | text += tr(", or select <b>New Document</b> to create a new document."); | ||
558 | text += tr("<br><br>Click and hold for document properties."); | ||
559 | QWhatsThis::add( this, text ); | ||
560 | } | ||
561 | |||
562 | #include "fileselector.moc" | ||
563 | |||