00001 import os,FreeCAD,FreeCADGui,tempfile,time,zipfile,urllib,re
00002 from PyQt4 import QtGui
00003 from xml.etree.ElementTree import parse
00004
00005 def translate(context,text):
00006 "convenience function for the Qt translator"
00007 return str(QtGui.QApplication.translate(context, text, None, QtGui.QApplication.UnicodeUTF8).toUtf8())
00008
00009
00010
00011 text01 = translate("StartPage","FreeCAD Start Center")
00012 text02 = translate("StartPage","Start a new project")
00013 text03 = translate("StartPage","Recent Files")
00014 text04 = translate("StartPage","Latest videos")
00015 text05 = translate("StartPage","Latest news")
00016 text06 = translate("StartPage","On the web")
00017 text07 = translate("StartPage","This is the FreeCAD Homepage. Here you will be able to find a lot of information about FreeCAD, including tutorials, examples and user documentation.")
00018 text08 = translate("StartPage","FreeCAD Homepage")
00019 text09 = translate("StartPage","Example projects")
00020 text10 = translate("StartPage","Schenkel STEP file")
00021 text11 = translate("StartPage","Load a PartDesign example")
00022 text12 = translate("StartPage","Load a Drawing extraction")
00023 text13 = translate("StartPage","Load a Robot simulation example")
00024 text14 = translate("StartPage","Projects from the Web")
00025 text15 = translate("StartPage","Schenkel STEP")
00026 text16 = translate("StartPage","Complex Part")
00027 text17 = translate("StartPage","Close this window after opening or creating a file")
00028 text18 = translate("StartPage","Don't show me this window again next time")
00029 text19 = translate("StartPage","Designing parts")
00030 text20 = translate("StartPage","The <b>Part Design</b> workbench is designed to create complex pieces based on constrained 2D sketches. Use it to draw 2D shapes, constrain some of their elements and extrude them to form 3D pieces.")
00031 text21 = translate("StartPage","Example workflow")
00032 text22 = translate("StartPage","Part Design")
00033 text23 = translate("StartPage","Designing architectural elements")
00034 text24 = translate("StartPage","The <b>Architectural Design</b> workbench is specially designed for working with architectural elements such as walls or windows. Start by drawing 2D shapes, and use them as guides to build architecutral objects.")
00035 text25 = translate("StartPage","Architectual Design")
00036 text26 = translate("StartPage","Working with Meshes")
00037 text27 = translate("StartPage","The <b>Mesh Workbench</b> is used to work with Mesh objects. Meshes are simpler 3D objects than Part objects, but they are often easier to import and export to/from other applications.")
00038 text28 = translate("StartPage","FreeCAD offers you several tools to convert between Mesh and Part objects.")
00039 text29 = translate("StartPage","Work with Meshes")
00040 text30 = translate("StartPage","The complete workbench")
00041 text31 = translate("StartPage","FreeCAD default workbench")
00042 text32 = translate("StartPage","populated with some of the most commonly used tools.")
00043 text33 = translate("StartPage","file size:")
00044 text34 = translate("StartPage","creation time:")
00045 text35 = translate("StartPage","last modified:")
00046 text36 = translate("StartPage","location:")
00047 text37 = translate("StartPage","User manual")
00048 text38 = translate("StartPage","http://sourceforge.net/apps/mediawiki/free-cad/index.php?title=Online_Help_Toc")
00049 text39 = translate("StartPage","Tutorials")
00050 text40 = translate("StartPage","Python resources")
00051 text41 = translate("StartPage","File not found")
00052 text42 = translate("StartPage","from <a href=http://twitter.com/FreeCADNews>@FreeCADNews</a>")
00053 text43 = translate("StartPage","The FreeCAD-tutorial blog")
00054 text44 = translate("StartPage","from <a href=http://www.youtube.com/user/FreeCADNews?feature=mhee>FreeCADNews channel</a>")
00055 text45 = translate("StartPage","This is the official user manual of FreeCAD, built, maintained and translated by the FreeCAD community.")
00056 text46 = translate("StartPage","The tutorials section on the FreeCAD website")
00057 text47 = translate("StartPage","The section of the FreeCAd website dedicate dto python scripting, with examples, explanations, and API commands.")
00058 text48 = translate("StartPage","A blog dedicated to teaching FreeCAD, maintained by members of the FreeCAD community")
00059
00060
00061
00062 page = """
00063 <html>
00064 <head>
00065 <title>FreeCAD - Start page</title>
00066 <script language="javascript">
00067 function JSONscriptRequest(fullUrl) {
00068 // REST request path
00069 this.fullUrl = fullUrl;
00070 // Get the DOM location to put the script tag
00071 this.headLoc = document.getElementsByTagName("head").item(0);
00072 // Generate a unique script tag id
00073 this.scriptId = 'JscriptId' + JSONscriptRequest.scriptCounter++;
00074 }
00075
00076 // Static script ID counter
00077 JSONscriptRequest.scriptCounter = 1;
00078
00079 JSONscriptRequest.prototype.buildScriptTag = function () {
00080 // Create the script tag
00081 this.scriptObj = document.createElement("script");
00082 // Add script object attributes
00083 this.scriptObj.setAttribute("type", "text/javascript");
00084 this.scriptObj.setAttribute("charset", "utf-8");
00085 this.scriptObj.setAttribute("src", this.fullUrl);
00086 this.scriptObj.setAttribute("id", this.scriptId);
00087 }
00088
00089 JSONscriptRequest.prototype.removeScriptTag = function () {
00090 // Destroy the script tag
00091 this.headLoc.removeChild(this.scriptObj);
00092 }
00093
00094 JSONscriptRequest.prototype.addScriptTag = function () {
00095 // Create the script tag
00096 this.headLoc.appendChild(this.scriptObj);
00097 }
00098
00099 function show(theText) {
00100 ddiv = document.getElementById("description");
00101 if (theText == "") theText = " ";
00102 ddiv.innerHTML = theText;
00103 }
00104
00105 function loadFeeds() {
00106 ddiv = document.getElementById("youtube");
00107 ddiv.innerHTML = "Fetching data from the web...";
00108 var obj=new JSONscriptRequest('http://gdata.youtube.com/feeds/base/users/FreeCADNews/favorites?alt=json-in-script&v=2&orderby=published&callback=showLinks');
00109 obj.buildScriptTag(); // Build the script tag
00110 obj.addScriptTag(); // Execute (add) the script tag
00111 ddiv.innerHTML = "Done fetching";
00112 ddiv = document.getElementById("news");
00113 ddiv.innerHTML = "Fetching data from the web...";
00114 var tobj=new JSONscriptRequest('http://twitter.com/status/user_timeline/FreeCADNews.json?count=10&callback=showTweets');
00115 tobj.buildScriptTag(); // Build the script tag
00116 tobj.addScriptTag(); // Execute (add) the script tag
00117 ddiv.innerHTML = "Done fetching";
00118 }
00119
00120 function showLinks(data) {
00121 ddiv = document.getElementById('youtube');
00122 ddiv.innerHTML = "Received";
00123 var feed = data.feed;
00124 var entries = feed.entry || [];
00125 var html = ['<ul>'];
00126 for (var i = 0; i < 5; i++) {
00127 html.push('<li><a href="',entries[i].link[0].href,'">', entries[i].title.$t, '</a></li>');
00128 }
00129 html.push('</ul>');
00130 ddiv.innerHTML = html.join('');
00131 }
00132 function showTweets(data) {
00133 ddiv = document.getElementById('news');
00134 ddiv.innerHTML = "Received";
00135 var html = ['<ul>'];
00136 for (var i = 0; i < Math.min(5,data.length); i++) {
00137 tf = placeLinks(data[i].text);
00138 html.push('<li>',tf,'</li>');
00139 }
00140 html.push('</ul>');
00141 ddiv.innerHTML = html.join('');
00142 }
00143 function placeLinks(text) {
00144 result=text.replace(/(https?:\/\/([-\w\.]+)+(:\d+)?(\/([\w\/_\.]*(\?\S+)?)?)?)/g,'<a href="$1">$1</a>');
00145 return result;
00146 }
00147 </script>
00148 <style type="text/css">
00149 body {
00150 background: #171A2B url(Background.jpg);
00151 color: white;
00152 font-family: Arial, Helvetica, Sans;
00153 font-size: 11px;
00154 }
00155 a {
00156 color: #0092E8;
00157 font-weight: bold;
00158 text-decoration: none;
00159 padding: 2px;
00160 }
00161 a:hover {
00162 color: white;
00163 background: #0092E8;
00164 border-radius: 5px;
00165 }
00166 p {
00167 text-align: justify;
00168 }
00169 .left {
00170 text-align: left;
00171 }
00172 h1 {
00173 font-size: 3em;
00174 letter-spacing: 2px;
00175 padding: 20px 0 0 80px;
00176 align: bottom;
00177 }
00178 h2 {
00179 font-size: 1.2em;
00180 }
00181 ul {
00182 list-style-type: none;
00183 padding: 0;
00184 }
00185 .column {
00186 width: 300px;
00187 float: left;
00188 margin-left: 10px;
00189 }
00190 .block {
00191 background: rgba(30,31,33,0.6);;
00192 border-radius: 5px;
00193 padding: 8px;
00194 margin-bottom: 10px;
00195 }
00196 .options {
00197 clear: both;
00198 }
00199 .from {
00200 font-size: 0.7em;
00201 font-weight: normal;
00202 }
00203 </style>
00204 </head>
00205
00206 <body onload="loadFeeds()">
00207
00208 <h1><img src="FreeCAD.png"> """ + text01 + """</h1>
00209
00210 <div class="column">
00211
00212 <div class="block">
00213 <h2>""" + text02 + """</h2>
00214 defaultworkbenches
00215 </div>
00216
00217 <div class="block">
00218 <h2>""" + text03 + """</h2>
00219 recentfiles
00220 </div>
00221
00222 <div class="block">
00223 <h2>""" + text04 + """ <span class="from">""" + text44 + """</span></h2>
00224 <div id="youtube">youtube videos</div>
00225 </div>
00226
00227 <div class="block">
00228 <h2>""" + text05 + """ <span class="from">""" + text42 + """</span></h2>
00229 <div id="news">news feed</div>
00230 </div>
00231
00232 </div>
00233
00234 <div class="column">
00235
00236 <div class="block">
00237 <h2>""" + text06 + """</h2>
00238 defaultlinks
00239 </div>
00240
00241 <div class="block">
00242 <h2>""" + text09 + """</h2>
00243 defaultexamples
00244 </div>
00245
00246
00247 customblocks
00248
00249 </div>
00250
00251 <div class="column" id="description">
00252
00253 </div>
00254
00255 <!--
00256 <form class="options">
00257 <input type="checkbox" name="closeThisDialog">
00258 """ + text17 + """<br/>
00259 <input type="checkbox" name="dontShowAgain">
00260 """ + text18 + """
00261 </form>
00262 -->
00263
00264 </body>
00265 </html>
00266 """
00267
00268 def getWebExamples():
00269 return """
00270 <ul>
00271 <li><a href="http://freecad-project.de/svn/ExampleData/FileFormates/Schenkel.stp">""" + text15 + """</a></li>
00272 <li><a href="http://freecad-project.de/svn/ExampleData/Examples/CAD/Complex.FCStd">""" + text16 + """</a></li>
00273 </ul>"""
00274
00275 def getExamples():
00276 return """
00277 <ul>
00278 <li><a href="LoadSchenkel.py">""" + text10 + """</a></li>
00279 <li><a href="LoadPartDesignExample.py">""" + text11 + """</a></li>
00280 <li><a href="LoadDrawingExample.py">""" + text12 + """</a></li>
00281 <li><a href="LoadRobotExample.py">""" + text13 + """</a></li>
00282 </ul>"""
00283
00284 def getLinks():
00285 return """
00286 <ul>
00287 <li><img src="web.png">
00288 <a onMouseover="show('<p>""" + text07 + """</p>')"
00289 onMouseout="show('')"
00290 href="http://free-cad.sf.net/">""" + text08 + """</a></li>
00291 <li><img src="web.png">
00292 <a onMouseover="show('<p>""" + text45 + """</p>')"
00293 onMouseout="show('')"
00294 href=""" + text38 + """>""" + text37 + """</a></li>
00295 <li><img src="web.png">
00296 <a onMouseover="show('<p>""" + text46 + """</p>')"
00297 onMouseout="show('')"
00298 href="http://sourceforge.net/apps/mediawiki/free-cad/index.php?title=Tutorials">""" + text39 + """</a></li>
00299 <li><img src="web.png">
00300 <a onMouseover="show('<p>""" + text47 + """</p>')"
00301 onMouseout="show('')"
00302 href="http://sourceforge.net/apps/mediawiki/free-cad/index.php?title=Power_users_hub">""" + text40 + """</a></li>
00303 <li><img src="web.png">
00304 <a onMouseover="show('<p>""" + text48 + """</p>')"
00305 onMouseout="show('')"
00306 href="http://freecad-tutorial.blogspot.com/">""" + text43 + """</a></li>
00307 </ul>"""
00308
00309 def getWorkbenches():
00310 return """
00311 <ul>
00312 <li><img src="PartDesign.png">
00313 <a onMouseover="show('<h3>""" + text19 + """</h3> \
00314 <p>""" + text20 + """</p><p><small>""" + text21 + """ \
00315 :</small></p><img src=PartDesignExample.png>')"
00316 onMouseout="show('')"
00317 href="PartDesign.py">""" + text22 + """</a></li>
00318 <li><img src="ArchDesign.png">
00319 <a onMouseover="show('<h3>""" + text23 + """</h3> \
00320 <p>""" + text24 + """</p><p><small>""" + text21 + """ \
00321 :</small></p><img src=ArchExample.png>')"
00322 onMouseout="show('')"
00323 href="ArchDesign.py">""" + text25 + """</a></li>
00324 <li><img src="Mesh.png">
00325 <a onMouseover="show('<h3>""" + text26 + """</h3> \
00326 <p>""" + text27 + """</p><p>""" + text28 + """</p>')"
00327 onMouseout="show('')"
00328 href="Mesh.py">""" + text29 + """</a></li>
00329 <li><img src="Complete.png">
00330 <a onMouseover="show('<h3>""" + text30 +"""</h3> \
00331 <p>This is the <b>""" + text31 + """</b>, \
00332 """ + text32 + """</p>')"
00333 onMouseout="show('')"
00334 href="DefaultWorkbench.py">""" + text31 + """</a></li>
00335 </ul>
00336 """
00337
00338 def getInfo(filename):
00339 "returns available file information"
00340
00341 def getLocalTime(timestamp):
00342 "returns a local time from a timestamp"
00343
00344 return time.strftime("%m/%d/%Y %H:%M:%S",time.localtime(timestamp))
00345
00346 def getSize(size):
00347 "returns a human-readable size"
00348
00349 if size > 1024*1024:
00350 hsize = str(size/(1024*1024)) + "Mb"
00351 elif size > 1024:
00352 hsize = str(size/1024) + "Kb"
00353 else:
00354 hsize = str(size) + "b"
00355 return hsize
00356
00357 html = '<h3>'+os.path.basename(filename)+'</h3>'
00358
00359 if os.path.exists(filename):
00360
00361 s = os.stat(filename)
00362 html += "<p>" + text33 + " " + getSize(s.st_size) + "<br/>"
00363 html += text34 + " " + getLocalTime(s.st_ctime) + "<br/>"
00364 html += text35 + " " + getLocalTime(s.st_mtime) + "<br/>"
00365 html += "<span>" + text36 + " " + filename + "</span></p>"
00366
00367 if os.path.splitext(filename)[1] in [".fcstd",".FcStd"]:
00368 zfile=zipfile.ZipFile(filename)
00369 files=zfile.namelist()
00370
00371 if files[0] == "Document.xml":
00372 html += "<p>FreeCAD Standard File</p>"
00373 image="thumbnails/Thumbnail.png"
00374 if image in files:
00375 image=zfile.read(image)
00376 thumbfile = tempfile.mkstemp(suffix='.png')[1]
00377 thumb = open(thumbfile,"wb")
00378 thumb.write(image)
00379 thumb.close()
00380 html += '<img src=file://'
00381
00382 html += thumbfile + '><br/>'
00383 else:
00384 html += "<p>" + text41 + "</p>"
00385
00386 return html
00387
00388 def getRecentFiles():
00389 "returns a list of 3 latest recent files"
00390
00391 rf=FreeCAD.ParamGet("User parameter:BaseApp/Preferences/RecentFiles")
00392 ct=rf.GetInt("RecentFiles")
00393 html = '<ul>'
00394 for i in range(3):
00395 if i < ct:
00396 mr = rf.GetString("MRU%d" % (i))
00397 fn = os.path.basename(mr)
00398 html += '<li><a '
00399 html += 'onMouseover="show(\''+getInfo(mr)+'\')" '
00400 html += 'onMouseout="show(\'\')" '
00401 html += 'href="LoadMRU'+str(i)+'.py">'
00402 html += fn
00403 html += '</a></li>'
00404 html += '</ul>'
00405 return html
00406
00407 def getFeed(url,numitems=3):
00408 "returns a html list with links from the given RSS feed url"
00409 xml = parse(urllib.urlopen(url)).getroot()
00410 items = []
00411 channel = xml.find('channel')
00412 for element in channel.findall('item'):
00413 items.append({
00414 'title': element.find('title').text,
00415 'description': element.find('description').text,
00416 'link': element.find('link').text,
00417 })
00418 if len(items) > numitems:
00419 items = items[:numitems]
00420 resp = '<ul>'
00421 for item in items:
00422 descr = re.compile("style=\".*?\"").sub('',item['description'])
00423 descr = re.compile("alt=\".*?\"").sub('',descr)
00424 descr = re.compile("\"").sub('',descr)
00425 d1 = re.findall("<img.*?>",descr)[0]
00426 d2 = re.findall("<span>.*?</span>",descr)[0]
00427 descr = "<h3>" + item['title'] + "</h3>"
00428 descr += d1 + "<br/>"
00429 descr += d2
00430 resp += '<li><a onMouseover="show(\''
00431 resp += descr
00432 resp += '\')" onMouseout="show(\'\')" href="'
00433 resp += item['link']
00434 resp += '">'
00435 resp += item['title']
00436 resp += '</a></li>'
00437 resp += '</ul>'
00438 print resp
00439 return resp
00440
00441 def getCustomBlocks():
00442 "fetches custom html files in FreeCAD user dir"
00443 output = ""
00444 return output
00445
00446 def handle():
00447 "returns the complete html startpage"
00448
00449
00450 recentfiles = getRecentFiles()
00451 html = page.replace("recentfiles",recentfiles)
00452
00453
00454 html = html.replace("defaultworkbenches",getWorkbenches())
00455
00456
00457 html = html.replace("defaultlinks",getLinks())
00458
00459
00460 html = html.replace("defaultexamples",getExamples())
00461
00462
00463
00464
00465
00466 html = html.replace("customblocks",getCustomBlocks())
00467
00468 return html
00469