]> Shamusworld >> Repos - architektonas/blob - src/forms/librarywidget.cpp
Fixed Library Browser...
[architektonas] / src / forms / librarywidget.cpp
1 // librarywidget.cpp
2 //
3 // Part of the Architektonas Project
4 // Originally part of QCad Community Edition by Andrew Mustun
5 // Extensively rewritten and refactored by James L. Hammons
6 // Portions copyright (C) 2001-2003 RibbonSoft
7 // Copyright (C) 2010 Underground Software
8 // See the README and GPLv2 files for licensing and warranty information
9 //
10 // JLH = James L. Hammons <jlhamm@acm.org>
11 //
12 // Who  When        What
13 // ---  ----------  -----------------------------------------------------------
14 // JLH  05/10/2010  Created this file. :-)
15 // JLH  08/28/2010  Restored functionality to library browser
16 //
17
18 #include "librarywidget.h"
19
20 #include "actionhandler.h"
21 #include "actionlibraryinsert.h"
22 #include "drawing.h"
23 #include "rs_staticgraphicview.h"
24 #include "rs_system.h"
25 #include "paintinterface.h"
26
27 LibraryWidget::LibraryWidget(QWidget * parent/*= 0*/, Qt::WindowFlags flags/*= 0*/):
28         QWidget(parent, flags), actionHandler(NULL)
29 {
30 #if 0
31 std::cout << "LibraryWidget::LibraryWidget()" << std::endl;
32 #endif
33         ui.setupUi(this);
34         ui.lvDirectory->setColumnCount(1);
35
36         QStringList directoryList = RS_SYSTEM->getDirectoryList("library");
37 #if 0
38 std::cout << "directorySize = " << directoryList.size() << std::endl;
39
40 for(int i=0; i<directoryList.size(); i++)
41         std::cout << directoryList.at(i).toLocal8Bit().constData() << std::endl;
42
43 std::cout.flush();
44 #endif
45
46         for(QStringList::Iterator it=directoryList.begin(); it!=directoryList.end(); it++)
47                 appendTree(NULL, (*it));
48 }
49
50 LibraryWidget::~LibraryWidget()
51 {
52 }
53
54 void LibraryWidget::setActionHandler(ActionHandler * ah)
55 {
56         actionHandler = ah;
57 }
58
59 /**
60  * Escape releases focus.
61  */
62 void LibraryWidget::keyPressEvent(QKeyEvent * e)
63 {
64         switch (e->key())
65         {
66         case Qt::Key_Escape:
67                 emit escape();
68                 break;
69
70         default:
71                 QWidget::keyPressEvent(e);
72                 break;
73         }
74 }
75
76 /**
77  * Insert.
78  */
79 void LibraryWidget::insert()
80 {
81         QListWidgetItem * item = ui.ivPreview->currentItem();
82         QString dxfPath = getItemPath(item);
83
84         if (QFileInfo(dxfPath).isReadable())
85         {
86                 if (actionHandler)
87                 {
88                         ActionInterface * a = actionHandler->setCurrentAction(RS2::ActionLibraryInsert);
89
90                         if (a)
91                         {
92                                 ActionLibraryInsert * action = (ActionLibraryInsert *)a;
93                                 action->setFile(dxfPath);
94                         }
95                         else
96                         {
97                                 RS_DEBUG->print(RS_Debug::D_ERROR, "LibraryWidget::insert:"
98                                         "Cannot create action ActionLibraryInsert");
99                         }
100                 }
101         }
102         else
103         {
104                 RS_DEBUG->print(RS_Debug::D_ERROR,
105                         "LibraryWidget::insert: Can't read file: '%s'", dxfPath.toLatin1().data());
106         }
107 }
108
109 /**
110  * Appends the given directory to the given list view item. Called recursively until all
111  * library directories are appended.
112  */
113 void LibraryWidget::appendTree(QTreeWidgetItem * item, QString directory)
114 {
115         QDir dir(directory);
116
117         if (!dir.exists())
118                 return;
119
120         // read subdirectories of this directory:
121         QStringList lDirectoryList = dir.entryList(QDir::Dirs, QDir::Name);
122
123         for(QStringList::Iterator it=lDirectoryList.begin(); it!=lDirectoryList.end(); it++)
124         {
125                 if ((*it) != "." && (*it) != "..")
126                 {
127                         // Look for an item already existing and take this instead of
128                         // making a new one:
129                         QTreeWidgetItem * newItem = NULL;
130                         QTreeWidgetItem * searchItem =
131                                 (item ? item->child(0) : ui.lvDirectory->topLevelItem(0));
132
133                         if (searchItem)
134                         {
135                                 for(int i=0; i<searchItem->childCount(); i++)
136                                 {
137                                         if (searchItem->child(i)->text(0) == (*it))
138                                         {
139                                                 newItem = searchItem->child(i);
140                                                 break;
141                                         }
142                                 }
143                         }
144
145                         // Create new item if no existing was found:
146                         if (!newItem)
147                         {
148                                 QStringList list;
149                                 list << (*it);
150                                 newItem = (item ? new QTreeWidgetItem(item, list) : new QTreeWidgetItem(ui.lvDirectory, list));
151                         }
152
153                         appendTree(newItem, directory + "/" + (*it));
154                 }
155         }
156 }
157
158 /**
159  * Updates the icon preview.
160  */
161 void LibraryWidget::updatePreview(QTreeWidgetItem * item, int /*column*/)
162 {
163         if (!item)
164                 return;
165
166         QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
167
168         // dir from the point of view of the library browser (e.g. /mechanical/screws)
169         QString directory = getItemDir(item);
170         ui.ivPreview->clear();
171
172         // List of all directories that contain part libraries:
173         QStringList directoryList = RS_SYSTEM->getDirectoryList("library");
174         QStringList::Iterator it;
175         QDir itemDir;
176         QStringList itemPathList;
177         QStringList filter;
178         filter << "*.dxf";
179
180         // Look in all possible system directories for DXF files in the current library path:
181         for(it=directoryList.begin(); it!=directoryList.end(); ++it)
182         {
183                 itemDir.setPath((*it) + directory);
184
185                 if (itemDir.exists())
186                 {
187                         QStringList itemNameList = itemDir.entryList(filter, QDir::Files, QDir::Name);
188                         QStringList::Iterator it2;
189
190                         for(it2=itemNameList.begin(); it2!=itemNameList.end(); ++it2)
191                                 itemPathList += itemDir.path() + "/" + (*it2);
192                 }
193         }
194
195         // Sort entries:
196         itemPathList.sort();
197
198         // Fill items into icon view:
199         QListWidgetItem * newItem;
200
201         for(it=itemPathList.begin(); it!=itemPathList.end(); ++it)
202         {
203 //              QString label = QFileInfo(*it).baseName(true);
204                 QString label = QFileInfo(*it).completeBaseName();
205                 QPixmap pixmap = getPixmap(directory, QFileInfo(*it).fileName(), (*it));
206 //              newItem = new QListWidgetItem(ui.ivPreview, label, pixmap);
207                 newItem = new QListWidgetItem(QIcon(pixmap), label, ui.ivPreview);
208 //Doesn't do what we want...
209 //              newItem->setSizeHint(QSize(64, 64));
210         }
211
212         QApplication::restoreOverrideCursor();
213 }
214
215 /**
216  * @return Directory (in terms of the List view) to the given item (e.g. /mechanical/screws)
217  * (called recursively)
218  */
219 QString LibraryWidget::getItemDir(QTreeWidgetItem * item)
220 {
221         if (!item)
222                 return "";
223
224         QTreeWidgetItem * parent = item->parent();
225
226         return getItemDir(parent) + QString("/%1").arg(item->text(0));
227 }
228
229 /**
230  * @return Path of the DXF file that is represented by the given item.
231  */
232 QString LibraryWidget::getItemPath(QListWidgetItem * item)
233 {
234         QString dir = getItemDir(ui.lvDirectory->currentItem());
235
236         if (item)
237         {
238                 // List of all directories that contain part libraries:
239                 QStringList directoryList = RS_SYSTEM->getDirectoryList("library");
240                 QStringList::Iterator it;
241                 QDir itemDir;
242
243                 // Look in all possible system directories for DXF files in the current library path:
244                 for(it=directoryList.begin(); it!=directoryList.end(); ++it)
245                 {
246                         itemDir.setPath((*it) + dir);
247
248                         if (itemDir.exists())
249                         {
250                                 QString f = (*it) + dir + "/" + item->text() + ".dxf";
251
252                                 if (QFileInfo(f).isReadable())
253                                         return f;
254                         }
255                 }
256         }
257
258         return "";
259 }
260
261 /**
262  * @return Pixmap that serves as icon for the given DXF File.
263  * The existing PNG file is returned or created and returned..
264  *
265  * @param dir Library directory (e.g. "/mechanical/screws")
266  * @param dxfFile File name (e.g. "screw1.dxf")
267  * @param dxfPath Full path to the existing DXF file on disk
268  *                          (e.g. /home/tux/.qcad/library/mechanical/screws/screw1.dxf)
269  */
270 QPixmap LibraryWidget::getPixmap(const QString & dir, const QString & dxfFile,
271         const QString & dxfPath)
272 {
273         QString pngFile = getPathToPixmap(dir, dxfFile, dxfPath);
274         QFileInfo fiPng(pngFile);
275
276         // Found existing thumbnail:
277         if (fiPng.isFile())
278                 return QPixmap(pngFile);
279         // Default thumbnail:
280         else
281                 return QPixmap(64, 64);
282 }
283
284 /**
285  * @return Path to the thumbnail of the given DXF file. If no thumbnail exists, one is
286  * created in the user's home. If no thumbnail can be created, an empty string is returned.
287  */
288 QString LibraryWidget::getPathToPixmap(const QString & dir, const QString & dxfFile,
289         const QString & dxfPath)
290 {
291         RS_DEBUG->print("LibraryWidget::getPathToPixmap: dir: '%s' dxfFile: '%s' dxfPath: '%s'",
292                 dir.toLatin1().data(), dxfFile.toLatin1().data(), dxfPath.toLatin1().data());
293
294         // List of all directories that contain part libraries:
295         QStringList directoryList = RS_SYSTEM->getDirectoryList("library");
296         directoryList.prepend(RS_SYSTEM->getHomeDir() + "/.qcad/library");
297         QStringList::Iterator it;
298
299         QFileInfo fiDxf(dxfPath);
300         QString itemDir;
301         QString pngPath;
302
303         // look in all possible system directories for PNG files
304         //  in the current library path:
305         for(it=directoryList.begin(); it!=directoryList.end(); ++it)
306         {
307                 itemDir = (*it) + dir;
308 //              pngPath = itemDir + "/" + fiDxf.baseName(true) + ".png";
309                 pngPath = itemDir + "/" + fiDxf.completeBaseName() + ".png";
310                 RS_DEBUG->print("LibraryWidget::getPathToPixmap: checking: '%s'",
311                         pngPath.toLatin1().data());
312                 QFileInfo fiPng(pngPath);
313
314                 // the thumbnail exists:
315                 if (fiPng.isFile())
316                 {
317                         RS_DEBUG->print("LibraryWidget::getPathToPixmap: dxf date: %s, png date: %s",
318                                 fiDxf.lastModified().toString().toLatin1().data(), fiPng.lastModified().toString().toLatin1().data());
319
320                         if (fiPng.lastModified() > fiDxf.lastModified())
321                         {
322                                 RS_DEBUG->print("LibraryWidget::getPathToPixmap: thumbnail found: '%s'",
323                                         pngPath.toLatin1().data());
324                                 return pngPath;
325                         }
326                         else
327                         {
328                                 RS_DEBUG->print("LibraryWidget::getPathToPixmap: thumbnail needs to be updated: '%s'",
329                                         pngPath.toLatin1().data());
330                         }
331                 }
332         }
333
334         // the thumbnail must be created in the user's home.
335
336         // create all directories needed:
337         RS_SYSTEM->createHomePath("/.qcad/library" + dir);
338         /*QString d = "/.qcad/library" + dir;
339         QDir dr;
340
341         QStringList dirs = QStringList::split('/', d, false);
342         QString created = RS_SYSTEM->getHomeDir();
343         for (it=dirs.begin(); it!=dirs.end(); ++it) {
344                 created += QString("/%1").arg(*it);
345
346                 if (created.isEmpty() || QFileInfo(created).isDir() || dr.mkdir(created, true)) {
347         RS_DEBUG->print("LibraryWidget: Created directory '%s'",
348         created.toLatin1().data());
349                 }
350                 else {
351         RS_DEBUG->print(RS_Debug::D_ERROR,
352         "LibraryWidget: Cannot create directory '%s'",
353         created.toLatin1().data());
354                         return "";
355                 }
356 }
357         */
358
359         QString d = RS_SYSTEM->getHomeDir() + "/.qcad/library" + dir;
360
361 //      pngPath = d + "/" + fiDxf.baseName(true) + ".png";
362         pngPath = d + "/" + fiDxf.completeBaseName() + ".png";
363
364         QPixmap * buffer = new QPixmap(128, 128);
365 //      RS_PainterQt * painter = new RS_PainterQt(buffer);
366         QPainter qpntr(buffer);
367         PaintInterface * painter = new PaintInterface(&qpntr);
368 //      painter->setBackgroundColor(RS_Color(255, 255, 255));
369 //      painter->eraseRect(0, 0, 128, 128);
370 //      qpntr.setBackgroundColor(RS_Color(255, 255, 255));
371         qpntr.setBackground(Qt::white);
372         qpntr.eraseRect(0, 0, 128, 128);
373
374         RS_StaticGraphicView gv(128, 128, painter);
375         Drawing graphic;
376
377         if (graphic.open(dxfPath, RS2::FormatUnknown))
378         {
379                 RS_Color black(0, 0, 0);
380
381                 for(RS_Entity * e=graphic.firstEntity(RS2::ResolveAll); e!=NULL; e=graphic.nextEntity(RS2::ResolveAll))
382                 {
383                         RS_Pen pen = e->getPen();
384                         pen.setColor(black);
385                         e->setPen(pen);
386                 }
387
388                 gv.setContainer(&graphic);
389                 gv.zoomAuto(false);
390                 gv.drawEntity(&graphic, true);
391
392 #if 0
393                 QImageIO iio;
394                 QImage img;
395                 img = *buffer;
396                 img = img.smoothScale(64, 64);
397                 iio.setImage(img);
398                 iio.setFileName(pngPath);
399                 iio.setFormat("PNG");
400
401                 if (!iio.write())
402                 {
403                         pngPath = "";
404                         RS_DEBUG->print(RS_Debug::D_ERROR,
405                                 "LibraryWidget::getPathToPixmap: Cannot write thumbnail: '%s'",
406                                 pngPath.toLatin1().data());
407                 }
408 #else
409 #warning "LibraryWidget::getPathToPixmap(): Needs porting to Qt4... !!! FIX !!!"
410 #endif
411         }
412         else
413         {
414                 RS_DEBUG->print(RS_Debug::D_ERROR, "LibraryWidget::getPathToPixmap: Cannot open file: '%s'", dxfPath.toLatin1().data());
415         }
416
417         delete painter;
418         delete buffer;
419
420         return pngPath;
421 }