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
17 // JLH 09/07/2010 Fully fixed thumbnail rendering
21 Note that this is basically just a way to get a block from a file; it's unclear
22 that it does so and the doco (such as it was) didn't mention it either. So what
23 we need is to make it very clear that inserting is to the BLOCK list and not
24 the document--perhaps we need to fold it into the block list, and make the
25 insert function insert into the block list only...
26 Also, it would be useful to have some information like base unit, dimensions, etc.
29 #include "librarywidget.h"
31 #include "actionhandler.h"
32 #include "actionlibraryinsert.h"
34 #include "staticgraphicview.h"
36 #include "paintinterface.h"
38 LibraryWidget::LibraryWidget(QWidget * parent/*= 0*/, Qt::WindowFlags flags/*= 0*/):
39 QWidget(parent, flags), actionHandler(NULL)
42 std::cout << "LibraryWidget::LibraryWidget()" << std::endl;
45 ui.lvDirectory->setColumnCount(1);
47 QStringList directoryList = SYSTEM->getDirectoryList("library");
49 std::cout << "directorySize = " << directoryList.size() << std::endl;
51 for(int i=0; i<directoryList.size(); i++)
52 std::cout << directoryList.at(i).toLocal8Bit().constData() << std::endl;
57 for(QStringList::Iterator it=directoryList.begin(); it!=directoryList.end(); it++)
58 appendTree(NULL, (*it));
61 LibraryWidget::~LibraryWidget()
65 void LibraryWidget::setActionHandler(ActionHandler * ah)
71 * Escape releases focus.
73 void LibraryWidget::keyPressEvent(QKeyEvent * e)
82 QWidget::keyPressEvent(e);
90 void LibraryWidget::insert()
92 QListWidgetItem * item = ui.ivPreview->currentItem();
93 QString dxfPath = getItemPath(item);
95 if (QFileInfo(dxfPath).isReadable())
99 ActionInterface * a = actionHandler->setCurrentAction(RS2::ActionLibraryInsert);
103 ActionLibraryInsert * action = (ActionLibraryInsert *)a;
104 action->setFile(dxfPath);
108 DEBUG->print(Debug::D_ERROR, "LibraryWidget::insert:"
109 "Cannot create action ActionLibraryInsert");
115 DEBUG->print(Debug::D_ERROR,
116 "LibraryWidget::insert: Can't read file: '%s'", dxfPath.toLatin1().data());
121 * Appends the given directory to the given list view item. Called recursively until all
122 * library directories are appended.
124 void LibraryWidget::appendTree(QTreeWidgetItem * item, QString directory)
131 // read subdirectories of this directory:
132 QStringList lDirectoryList = dir.entryList(QDir::Dirs, QDir::Name);
134 for(QStringList::Iterator it=lDirectoryList.begin(); it!=lDirectoryList.end(); it++)
136 if ((*it) != "." && (*it) != "..")
138 // Look for an item already existing and take this instead of
140 QTreeWidgetItem * newItem = NULL;
141 QTreeWidgetItem * searchItem =
142 (item ? item->child(0) : ui.lvDirectory->topLevelItem(0));
146 for(int i=0; i<searchItem->childCount(); i++)
148 if (searchItem->child(i)->text(0) == (*it))
150 newItem = searchItem->child(i);
156 // Create new item if no existing was found:
161 newItem = (item ? new QTreeWidgetItem(item, list) : new QTreeWidgetItem(ui.lvDirectory, list));
164 //This is picking up the directory tree TWICE, but ONLY if there are no thumbnails!
165 //Actually, only if there is no corresponding thumbnail DIRECTORY under .architektonas...
167 //It was picking up .architektonas from the home directory in rs_system.cpp, that's why!
168 //printf("LibraryWidget::appendTree: *it=\"%s\"\n", (*it).toAscii().data());
169 appendTree(newItem, directory + "/" + (*it));
175 * Updates the icon preview.
177 void LibraryWidget::updatePreview(QTreeWidgetItem * item, int /*column*/)
182 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
184 // dir from the point of view of the library browser (e.g. /mechanical/screws)
185 QString directory = getItemDir(item);
186 ui.ivPreview->clear();
188 // List of all directories that contain part libraries:
189 QStringList directoryList = SYSTEM->getDirectoryList("library");
190 QStringList::Iterator it;
192 QStringList itemPathList;
196 // Look in all possible system directories for DXF files in the current library path:
197 for(it=directoryList.begin(); it!=directoryList.end(); ++it)
199 itemDir.setPath((*it) + directory);
201 if (itemDir.exists())
203 QStringList itemNameList = itemDir.entryList(filter, QDir::Files, QDir::Name);
204 QStringList::Iterator it2;
206 for(it2=itemNameList.begin(); it2!=itemNameList.end(); ++it2)
207 itemPathList += itemDir.path() + "/" + (*it2);
214 // Fill items into icon view:
215 QListWidgetItem * newItem;
217 for(it=itemPathList.begin(); it!=itemPathList.end(); ++it)
219 // QString label = QFileInfo(*it).baseName(true);
220 QString label = QFileInfo(*it).completeBaseName();
221 QPixmap pixmap = getPixmap(directory, QFileInfo(*it).fileName(), (*it));
222 // newItem = new QListWidgetItem(ui.ivPreview, label, pixmap);
223 newItem = new QListWidgetItem(QIcon(pixmap), label, ui.ivPreview);
224 //Doesn't do what we want...
225 // newItem->setSizeHint(QSize(64, 64));
226 //printf("LibraryWidget: label = \"%s\"\n", label.toAscii().data());
229 QApplication::restoreOverrideCursor();
233 * @return Directory (in terms of the List view) to the given item (e.g. /mechanical/screws)
234 * (called recursively)
236 QString LibraryWidget::getItemDir(QTreeWidgetItem * item)
241 QTreeWidgetItem * parent = item->parent();
243 return getItemDir(parent) + QString("/%1").arg(item->text(0));
247 * @return Path of the DXF file that is represented by the given item.
249 QString LibraryWidget::getItemPath(QListWidgetItem * item)
251 QString dir = getItemDir(ui.lvDirectory->currentItem());
255 // List of all directories that contain part libraries:
256 QStringList directoryList = SYSTEM->getDirectoryList("library");
257 QStringList::Iterator it;
260 // Look in all possible system directories for DXF files in the current library path:
261 for(it=directoryList.begin(); it!=directoryList.end(); ++it)
263 itemDir.setPath((*it) + dir);
265 if (itemDir.exists())
267 QString f = (*it) + dir + "/" + item->text() + ".dxf";
269 if (QFileInfo(f).isReadable())
279 * @return Pixmap that serves as icon for the given DXF File.
280 * The existing PNG file is returned or created and returned..
282 * @param dir Library directory (e.g. "/mechanical/screws")
283 * @param dxfFile File name (e.g. "screw1.dxf")
284 * @param dxfPath Full path to the existing DXF file on disk
285 * (e.g. /home/tux/.architektonas/library/mechanical/screws/screw1.dxf)
287 QPixmap LibraryWidget::getPixmap(const QString & dir, const QString & dxfFile,
288 const QString & dxfPath)
290 QString pngFile = getPathToPixmap(dir, dxfFile, dxfPath);
291 QFileInfo fiPng(pngFile);
293 // Found existing thumbnail:
295 return QPixmap(pngFile);
296 // Default thumbnail:
298 return QPixmap(64, 64);
302 * @return Path to the thumbnail of the given DXF file. If no thumbnail exists, one is
303 * created in the user's home. If no thumbnail can be created, an empty string is returned.
305 QString LibraryWidget::getPathToPixmap(const QString & dir, const QString & dxfFile,
306 const QString & dxfPath)
308 DEBUG->print("LibraryWidget::getPathToPixmap: dir: '%s' dxfFile: '%s' dxfPath: '%s'",
309 dir.toLatin1().data(), dxfFile.toLatin1().data(), dxfPath.toLatin1().data());
311 // List of all directories that contain part libraries:
312 QStringList directoryList = SYSTEM->getDirectoryList("library");
313 directoryList.prepend(SYSTEM->getHomeDir() + "/.architektonas/library");
314 QStringList::Iterator it;
316 QFileInfo fiDxf(dxfPath);
320 // look in all possible system directories for PNG files
321 // in the current library path:
322 for(it=directoryList.begin(); it!=directoryList.end(); ++it)
324 itemDir = (*it) + dir;
325 pngPath = itemDir + "/" + fiDxf.completeBaseName() + ".png";
326 DEBUG->print("LibraryWidget::getPathToPixmap: checking: '%s'",
327 pngPath.toLatin1().data());
328 QFileInfo fiPng(pngPath);
330 // the thumbnail exists:
333 DEBUG->print("LibraryWidget::getPathToPixmap: dxf date: %s, png date: %s",
334 fiDxf.lastModified().toString().toLatin1().data(), fiPng.lastModified().toString().toLatin1().data());
336 if (fiPng.lastModified() > fiDxf.lastModified())
338 DEBUG->print("LibraryWidget::getPathToPixmap: thumbnail found: '%s'",
339 pngPath.toLatin1().data());
344 DEBUG->print("LibraryWidget::getPathToPixmap: thumbnail needs to be updated: '%s'",
345 pngPath.toLatin1().data());
350 // The thumbnail must be created in the user's home.
351 // So, create all directories needed:
352 SYSTEM->createHomePath("/.architektonas/library" + dir);
353 QString d = SYSTEM->getHomeDir() + "/.architektonas/library" + dir;
354 pngPath = d + "/" + fiDxf.completeBaseName() + ".png";
356 QPixmap buffer(128, 128);
357 QPainter qpntr(&buffer);
358 PaintInterface * painter = new PaintInterface(&qpntr);
359 qpntr.setBackground(Qt::white);
360 qpntr.eraseRect(0, 0, 128, 128);
362 StaticGraphicView view(128, 128, painter);
365 if (drawing.open(dxfPath, RS2::FormatUnknown))
367 Color black(0, 0, 0);
369 // Set all pens in the drawing to BLACK
370 for(Entity * e=drawing.firstEntity(RS2::ResolveAll); e!=NULL; e=drawing.nextEntity(RS2::ResolveAll))
372 Pen pen = e->getPen();
377 view.setContainer(&drawing);
378 view.zoomAuto(false);
379 view.drawEntity(&drawing, true);
382 QImage image = buffer.toImage();
383 image.scaled(64, 64, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
384 writer.setFileName(pngPath);
385 writer.setFormat("png");
387 if (!writer.write(image))
389 DEBUG->print(Debug::D_ERROR,
390 "LibraryWidget::getPathToPixmap: Cannot write thumbnail: '%s'",
391 pngPath.toLatin1().data());
397 DEBUG->print(Debug::D_ERROR, "LibraryWidget::getPathToPixmap: Cannot open file: '%s'", dxfPath.toLatin1().data());