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
10 // JLH = James L. Hammons <jlhamm@acm.org>
13 // --- ---------- -----------------------------------------------------------
14 // JLH 05/10/2010 Created this file. :-)
15 // JLH 08/28/2010 Restored functionality to library browser
16 // JLH 09/06/2010 Partially fixed thumbnail rendering
22 - Picks up thumbnail directories twice--only once if thumbnail dir doesn't exist
25 #include "librarywidget.h"
27 #include "actionhandler.h"
28 #include "actionlibraryinsert.h"
30 #include "rs_staticgraphicview.h"
31 #include "rs_system.h"
32 #include "paintinterface.h"
34 LibraryWidget::LibraryWidget(QWidget * parent/*= 0*/, Qt::WindowFlags flags/*= 0*/):
35 QWidget(parent, flags), actionHandler(NULL)
38 std::cout << "LibraryWidget::LibraryWidget()" << std::endl;
41 ui.lvDirectory->setColumnCount(1);
43 QStringList directoryList = RS_SYSTEM->getDirectoryList("library");
45 std::cout << "directorySize = " << directoryList.size() << std::endl;
47 for(int i=0; i<directoryList.size(); i++)
48 std::cout << directoryList.at(i).toLocal8Bit().constData() << std::endl;
53 for(QStringList::Iterator it=directoryList.begin(); it!=directoryList.end(); it++)
54 appendTree(NULL, (*it));
57 LibraryWidget::~LibraryWidget()
61 void LibraryWidget::setActionHandler(ActionHandler * ah)
67 * Escape releases focus.
69 void LibraryWidget::keyPressEvent(QKeyEvent * e)
78 QWidget::keyPressEvent(e);
86 void LibraryWidget::insert()
88 QListWidgetItem * item = ui.ivPreview->currentItem();
89 QString dxfPath = getItemPath(item);
91 if (QFileInfo(dxfPath).isReadable())
95 ActionInterface * a = actionHandler->setCurrentAction(RS2::ActionLibraryInsert);
99 ActionLibraryInsert * action = (ActionLibraryInsert *)a;
100 action->setFile(dxfPath);
104 RS_DEBUG->print(RS_Debug::D_ERROR, "LibraryWidget::insert:"
105 "Cannot create action ActionLibraryInsert");
111 RS_DEBUG->print(RS_Debug::D_ERROR,
112 "LibraryWidget::insert: Can't read file: '%s'", dxfPath.toLatin1().data());
117 * Appends the given directory to the given list view item. Called recursively until all
118 * library directories are appended.
120 void LibraryWidget::appendTree(QTreeWidgetItem * item, QString directory)
127 // read subdirectories of this directory:
128 QStringList lDirectoryList = dir.entryList(QDir::Dirs, QDir::Name);
130 for(QStringList::Iterator it=lDirectoryList.begin(); it!=lDirectoryList.end(); it++)
132 if ((*it) != "." && (*it) != "..")
134 // Look for an item already existing and take this instead of
136 QTreeWidgetItem * newItem = NULL;
137 QTreeWidgetItem * searchItem =
138 (item ? item->child(0) : ui.lvDirectory->topLevelItem(0));
142 for(int i=0; i<searchItem->childCount(); i++)
144 if (searchItem->child(i)->text(0) == (*it))
146 newItem = searchItem->child(i);
152 // Create new item if no existing was found:
157 newItem = (item ? new QTreeWidgetItem(item, list) : new QTreeWidgetItem(ui.lvDirectory, list));
160 appendTree(newItem, directory + "/" + (*it));
166 * Updates the icon preview.
168 void LibraryWidget::updatePreview(QTreeWidgetItem * item, int /*column*/)
173 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
175 // dir from the point of view of the library browser (e.g. /mechanical/screws)
176 QString directory = getItemDir(item);
177 ui.ivPreview->clear();
179 // List of all directories that contain part libraries:
180 QStringList directoryList = RS_SYSTEM->getDirectoryList("library");
181 QStringList::Iterator it;
183 QStringList itemPathList;
187 // Look in all possible system directories for DXF files in the current library path:
188 for(it=directoryList.begin(); it!=directoryList.end(); ++it)
190 itemDir.setPath((*it) + directory);
192 if (itemDir.exists())
194 QStringList itemNameList = itemDir.entryList(filter, QDir::Files, QDir::Name);
195 QStringList::Iterator it2;
197 for(it2=itemNameList.begin(); it2!=itemNameList.end(); ++it2)
198 itemPathList += itemDir.path() + "/" + (*it2);
205 // Fill items into icon view:
206 QListWidgetItem * newItem;
208 for(it=itemPathList.begin(); it!=itemPathList.end(); ++it)
210 // QString label = QFileInfo(*it).baseName(true);
211 QString label = QFileInfo(*it).completeBaseName();
212 QPixmap pixmap = getPixmap(directory, QFileInfo(*it).fileName(), (*it));
213 // newItem = new QListWidgetItem(ui.ivPreview, label, pixmap);
214 newItem = new QListWidgetItem(QIcon(pixmap), label, ui.ivPreview);
215 //Doesn't do what we want...
216 // newItem->setSizeHint(QSize(64, 64));
219 QApplication::restoreOverrideCursor();
223 * @return Directory (in terms of the List view) to the given item (e.g. /mechanical/screws)
224 * (called recursively)
226 QString LibraryWidget::getItemDir(QTreeWidgetItem * item)
231 QTreeWidgetItem * parent = item->parent();
233 return getItemDir(parent) + QString("/%1").arg(item->text(0));
237 * @return Path of the DXF file that is represented by the given item.
239 QString LibraryWidget::getItemPath(QListWidgetItem * item)
241 QString dir = getItemDir(ui.lvDirectory->currentItem());
245 // List of all directories that contain part libraries:
246 QStringList directoryList = RS_SYSTEM->getDirectoryList("library");
247 QStringList::Iterator it;
250 // Look in all possible system directories for DXF files in the current library path:
251 for(it=directoryList.begin(); it!=directoryList.end(); ++it)
253 itemDir.setPath((*it) + dir);
255 if (itemDir.exists())
257 QString f = (*it) + dir + "/" + item->text() + ".dxf";
259 if (QFileInfo(f).isReadable())
269 * @return Pixmap that serves as icon for the given DXF File.
270 * The existing PNG file is returned or created and returned..
272 * @param dir Library directory (e.g. "/mechanical/screws")
273 * @param dxfFile File name (e.g. "screw1.dxf")
274 * @param dxfPath Full path to the existing DXF file on disk
275 * (e.g. /home/tux/.qcad/library/mechanical/screws/screw1.dxf)
277 QPixmap LibraryWidget::getPixmap(const QString & dir, const QString & dxfFile,
278 const QString & dxfPath)
280 QString pngFile = getPathToPixmap(dir, dxfFile, dxfPath);
281 QFileInfo fiPng(pngFile);
283 // Found existing thumbnail:
285 return QPixmap(pngFile);
286 // Default thumbnail:
288 return QPixmap(64, 64);
292 * @return Path to the thumbnail of the given DXF file. If no thumbnail exists, one is
293 * created in the user's home. If no thumbnail can be created, an empty string is returned.
295 QString LibraryWidget::getPathToPixmap(const QString & dir, const QString & dxfFile,
296 const QString & dxfPath)
298 RS_DEBUG->print("LibraryWidget::getPathToPixmap: dir: '%s' dxfFile: '%s' dxfPath: '%s'",
299 dir.toLatin1().data(), dxfFile.toLatin1().data(), dxfPath.toLatin1().data());
301 // List of all directories that contain part libraries:
302 QStringList directoryList = RS_SYSTEM->getDirectoryList("library");
303 directoryList.prepend(RS_SYSTEM->getHomeDir() + "/.architektonas/library");
304 QStringList::Iterator it;
306 QFileInfo fiDxf(dxfPath);
310 // look in all possible system directories for PNG files
311 // in the current library path:
312 for(it=directoryList.begin(); it!=directoryList.end(); ++it)
314 itemDir = (*it) + dir;
315 // pngPath = itemDir + "/" + fiDxf.baseName(true) + ".png";
316 pngPath = itemDir + "/" + fiDxf.completeBaseName() + ".png";
317 RS_DEBUG->print("LibraryWidget::getPathToPixmap: checking: '%s'",
318 pngPath.toLatin1().data());
319 QFileInfo fiPng(pngPath);
321 // the thumbnail exists:
324 RS_DEBUG->print("LibraryWidget::getPathToPixmap: dxf date: %s, png date: %s",
325 fiDxf.lastModified().toString().toLatin1().data(), fiPng.lastModified().toString().toLatin1().data());
327 if (fiPng.lastModified() > fiDxf.lastModified())
329 RS_DEBUG->print("LibraryWidget::getPathToPixmap: thumbnail found: '%s'",
330 pngPath.toLatin1().data());
335 RS_DEBUG->print("LibraryWidget::getPathToPixmap: thumbnail needs to be updated: '%s'",
336 pngPath.toLatin1().data());
341 // The thumbnail must be created in the user's home.
342 // So, create all directories needed:
343 RS_SYSTEM->createHomePath("/.architektonas/library" + dir);
345 QString d = RS_SYSTEM->getHomeDir() + "/.architektonas/library" + dir;
346 //printf("librarywidget: d = \"%s\"\n", d.toAscii().data());
348 // pngPath = d + "/" + fiDxf.baseName(true) + ".png";
349 pngPath = d + "/" + fiDxf.completeBaseName() + ".png";
350 //printf("librarywidget: pngPath = \"%s\"\n", pngPath.toAscii().data());
352 // Ugh. This is a mess and doesn't work right anyway...
353 // Problem is StaticGraphicView doesn't follow a standard rendering path,
354 // so all this crap just ends in failure. Not sure how to fix.
356 I suppose one way to do it would be to make a CreateImage() function in GraphicView,
357 then we wouldn't have all this messiness...
358 I think the way the redraw works is like that--it creates its own PaintInterface
359 and QPainter and sets "painter" equal to it... That being the case, it would be
360 a simple matter to modify StaticGraphicView to utilize that... Let's see...
361 Which it should be doing, but, for some reason, it fails. Dunno why.
363 It only fails for certain DXFs. Dunno why.
366 QPixmap buffer(128, 128);
367 QPainter qpntr(&buffer);
368 PaintInterface * painter = new PaintInterface(&qpntr);
369 qpntr.setBackground(Qt::white);
370 qpntr.eraseRect(0, 0, 128, 128);
372 RS_StaticGraphicView gv(128, 128, painter);
375 if (drawing.open(dxfPath, RS2::FormatUnknown))
377 RS_Color black(0, 0, 0);
379 // Set all pens in the drawing to BLACK
380 for(RS_Entity * e=drawing.firstEntity(RS2::ResolveAll); e!=NULL; e=drawing.nextEntity(RS2::ResolveAll))
382 RS_Pen pen = e->getPen();
387 gv.setContainer(&drawing);
389 //This works, but somehow doesn't work ALL the time
390 gv.drawEntity(&drawing, true);
393 QImage image = buffer.toImage();
394 image.scaled(64, 64, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
395 writer.setFileName(pngPath);
396 writer.setFormat("png");
398 if (!writer.write(image))
400 RS_DEBUG->print(RS_Debug::D_ERROR,
401 "LibraryWidget::getPathToPixmap: Cannot write thumbnail: '%s'",
402 pngPath.toLatin1().data());
408 RS_DEBUG->print(RS_Debug::D_ERROR, "LibraryWidget::getPathToPixmap: Cannot open file: '%s'", dxfPath.toLatin1().data());
418 QWidget::setMinimumSize: (/QMdi::ControlLabel) Negative sizes (-1,-1) are not possible
419 QPaintDevice: Cannot destroy paint device that is being painted
421 Program received signal SIGSEGV, Segmentation fault.
424 #0 0x085cd068 in ?? ()
425 #1 0xb7818bd0 in QPainter::~QPainter() () from /usr/lib/qt4/libQtGui.so.4
426 #2 0x081c1e8e in LibraryWidget::getPathToPixmap(QString const&, QString const&, QString const&) ()
427 #3 0x081c0fa6 in LibraryWidget::getPixmap(QString const&, QString const&, QString const&) ()
428 #4 0x081c0775 in LibraryWidget::updatePreview(QTreeWidgetItem*, int) ()
429 #5 0x08237d5e in LibraryWidget::qt_metacall(QMetaObject::Call, int, void**) ()