Work on export/import and other magics.

This commit is contained in:
Martin Rotter 2015-05-29 08:56:44 +02:00
parent 942dcf3adb
commit 3429228d41
23 changed files with 224 additions and 46 deletions

View file

@ -384,6 +384,10 @@ set(APP_SOURCES
src/miscellaneous/iofactory.cpp src/miscellaneous/iofactory.cpp
src/miscellaneous/autosaver.cpp src/miscellaneous/autosaver.cpp
# EXCEPTIONS sources.
src/exceptions/applicationexception.cpp
src/exceptions/ioexception.cpp
# CORE sources. # CORE sources.
src/core/messagesmodel.cpp src/core/messagesmodel.cpp
src/core/messagesproxymodel.cpp src/core/messagesproxymodel.cpp

View file

@ -2,17 +2,17 @@
<opml version="2.0"> <opml version="2.0">
<head> <head>
<title>RSS Guard</title> <title>RSS Guard</title>
<dateCreated>Wed, 27 May 2015 16:15:55 GMT</dateCreated> <dateCreated>Fri, 29 May 2015 06:54:31 GMT</dateCreated>
</head> </head>
<body> <body>
<outline text="Linux" description="Collections of GNU/Linux-related feeds."> <outline description="Collections of GNU/Linux-related feeds." rssguard:icon="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" text="Linux">
<outline xmlUrl="http://feeds.feedburner.com/linuxtoday/linux?format=xml" text="Linux Today" version="RSS" description="Linux Today - Linux News on Internet Time." encoding="UTF-8" title="Linux Today"/> <outline xmlUrl="http://feeds.feedburner.com/linuxtoday/linux?format=xml" description="Linux Today - Linux News on Internet Time." encoding="UTF-8" rssguard:icon="AAAAIgBRAFAAaQB4AG0AYQBwAEkAYwBvAG4ARQBuAGcAaQBuAGUAAAABAAAAAYlQTkcNChoKAAAADUlIRFIAAAAQAAAAEAgCAAAAkJFoNgAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAXpJREFUKJGV0k9LG0EcxvHvjLsbcMH0kB4MBIl7CEEMBHIIvfSYi+/AsxZ8HQEpHj3pW+ilkC54Eikl0EOhBAIrCTGHVEUCLWV3bbK7Mx42iFmkrc9thvnw+8MI9k94SQxAn+z/52vx7lQ+PbfbbSFEs9n8i1kCvV4PKBaL/2gpTRRFw+EQcBwH0EmYTL8k159kftvc3HumwmQyGQwGQKVSAeIfH+8/t+bDY4xVAHQWuK7r+76UslqtAurnt/R+fnkUXrz983U3C/r9PmDbdrlc1nEQ37iAMNeIA/Xru9Z6aQalVAocxykUCjrwVHAFmM5BbvtQJ6EQ5lKFMAxHo1EKLMtSwRVqDsh8DRArq8hlMB6Pp9MpsBjgtwcgrZX8VmatC+B53mw2A1qtFhDfngFCWhhr6BgVZUG60FKpVK/XAT27A3Tsh+dvfHcjmnzIgm63CzQaDdu2gVztvczXhPkKnYAUudePYLGlTqfztFFjfcdY3+G5iJd+7wdysI9hnZlHjQAAAABJRU5ErkJggv////8AAAAQAAAAEAAAAAAAAAAB" title="Linux Today" version="RSS" text="Linux Today"/>
<outline xmlUrl="http://www.linuxinsider.com/perl/syndication/rssfull.pl" text="LinuxInsider" version="RSS" description="LinuxInsider: Linux News &amp; Information from Around the World." encoding="UTF-8" title="LinuxInsider"/> <outline xmlUrl="http://www.linuxinsider.com/perl/syndication/rssfull.pl" description="LinuxInsider: Linux News &amp; Information from Around the World." encoding="UTF-8" rssguard:icon="AAAAIgBRAFAAaQB4AG0AYQBwAEkAYwBvAG4ARQBuAGcAaQBuAGUAAAABAAAAAYlQTkcNChoKAAAADUlIRFIAAAAQAAAAEAgCAAAAkJFoNgAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAFtJREFUKJFjNM8OYiAFsDAwMJyYspZI1RY5wSwQFiMjIwMDw////+FyEBFkAJFlIsk9UCdhBRDzMG0m2YZRDcQAlHiAx+7///+RYxo5Nsi1ATkucYlAbSM1eQMA4PEdCz0mjK8AAAAASUVORK5CYIL/////AAAAEAAAABAAAAAAAAAAAQ==" title="LinuxInsider" version="RSS" text="LinuxInsider"/>
<outline xmlUrl="http://lxer.com/module/newswire/headlines.rss" text="LXer: Linux News" version="RSS1" description="The world is talking about GNU/Linux and Free/Open Source Software." encoding="UTF-8" title="LXer: Linux News"/> <outline xmlUrl="http://lxer.com/module/newswire/headlines.rss" description="The world is talking about GNU/Linux and Free/Open Source Software." encoding="UTF-8" rssguard:icon="AAAAIgBRAFAAaQB4AG0AYQBwAEkAYwBvAG4ARQBuAGcAaQBuAGUAAAABAAAAAYlQTkcNChoKAAAADUlIRFIAAAAQAAAAEAgGAAAAH/P/YQAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAmNJREFUOI2lkt1L03EUxj+//eY0X6DhTOcUwgq1cIPQDDWnMoglWorRlXoV6P+QF4GXlczsooswEEzEMA1SEMWRF3WTOmlKpelyzbc2N5fbmu7bTZN8yYKeq3Nxns95zuHAf0qKFvb3dmF/0U8osE0kIoiNiyOrtJT8sjKpt71dhLd8CCE4laZFX1lJmlYrASijgBXXV9afPCU9+B31jowj6KWzs5OORx3iw737GJaXiQFmJRhuasa16hLaVK2kiAIqTCZpq+k2bZEIO6oI7hglz/1+goEgDqORhDNZtCkU3E1KYt3jwbvp3b9CVBaLRTi6uqiWZbq3twkXFFCpVjMzNIRlxUVjQyM1NTUYjUYJQHEQUF9fz0ZOLouyzM2EBHTeTeTJSR4vOzFfNVNbW7tn/qOmbdPiRlGRGC0uFtaSEnElNVXk6fNEX1+fONh7KAGAQW+Qzl4uZCcjA8JhTicmYtAbqKurOzT5SMD4+LjIV8Vin5vjsyzTkJKCd34eq9X69wROp1NMjY2RPDND28ICDxwOkGWuh8P09vTgWHKIYwGvBl9yccXFw6kp4rRaCs1m+gMBzskyijdvGRkdwePxiCMBHydei/SlRTYdX/CoT1JdVU15WRmq3BxCGg1VsSo+DQ3zbmJiz7PvKK2XCkTMdgCAb0CgopwLuedxdz9D6XGz+6tvITGRW62tmEwmSfk7YOREPKu+LUKhELJS5hoSTc3NUsudFjEwOIDP62M3skuyrKR8be1wAgCbzSb8fj9CCDQaDdnZ2RLA7NyscG+4Cf0IER8fj06nIzMz8/iH+hf9BPHg9ZQiSgntAAAAAElFTkSuQmCC/////wAAABAAAAAQAAAAAAAAAAE=" title="LXer: Linux News" version="RSS1" text="LXer: Linux News"/>
<outline xmlUrl="http://feeds2.feedburner.com/littleatomspodcast" text="Little Atoms" version="RSS" description="A Show About Ideas" encoding="UTF-8" title="Little Atoms"/> <outline xmlUrl="http://feeds2.feedburner.com/littleatomspodcast" description="A Show About Ideas" encoding="UTF-8" rssguard:icon="AAAAIgBRAFAAaQB4AG0AYQBwAEkAYwBvAG4ARQBuAGcAaQBuAGUAAAABAAAAAYlQTkcNChoKAAAADUlIRFIAAAAQAAAAEAgCAAAAkJFoNgAAAAlwSFlzAAAOxAAADsQBlSsOGwAAArpJREFUKJEl0rtK81AAAOBcTkzIaWzMaWxDq1SQUnFxUoqIUHeHTqKTDyD4DD6HUydnJydXL1SxSkWtRKO1KEZy4+Tec/7hf4Fv+ther+f7fhzHpVJJFMVCocBxHKU0yzKe5wVBIIT4vh8EQRRFjuOAOI4BAJqmYYyTJEmSRJIkWZanpqbSNGVZlhAiCAIAgFKaJAmIoojjOAjh9/e3oii1Wk2SJIZhCCGKokiSlGXZf55SGgQB+Pn5qVarAIA0TRVFwRiHYTg9PZ3n+Wg0GgwGHx8fpVJJ1/U0TVVVBTzPAwAkSUqSZH9/fzAYdDqdg4OD2dnZk5OTwWCgqqqu65ZlnZ+fV6tVEMcxIaTb7X5+fs7Pz2ua5nlep9NBCK2trUEIX15eer0eQuj5+bnRaACMcRRFp6enm5ub19fXEMKtra1ms3l4eHh0dNRut23bRggpinJxcbG7u8tvb2/zPF+v1+v1uqqqrVbLcZyNjY1ms0kIeXt7y7KMUur7frvdzrIMUEpd11UUxTRNAMDT0xNCaGFhIY7jlZUVTdMghLIsVyoVjPHd3R2IoohhmDzPTdPc29trNBo3Nzeu6xaLxeFw6LquYRgIoTiObdseDofAdV1K6WQyeXh4uL+/hxCenZ11u92dnZ3JZFKpVEzTNAxjaWnJNM3X11d+dXWVZVmO42ZmZvr9vmVZt7e3rVbLMIzl5WWEUBRFl5eXgiC8v79nWQZYlpVlWZKkcrns+/7j4yOEUNO0QqEQBAHG2PM8x3Ewxl9fXwzDAEqpKIr/tywuLvb7/bm5OY7jEEIAAEIIhLBcLo9GI8/z/v7+AM/zhJAwDBmGqdVqlNLf31/Lso6PjwVBqNfrxWKRYZjxeCyKYhiG/Pr6epIkeZ5HUZSmqSAIV1dXuq4rilKtVlVVtSxrPB5jjG3bliTpH5t5g55F2LrNAAAAAElFTkSuQmCC/////wAAABAAAAAQAAAAAAAAAAE=" title="Little Atoms" version="RSS" text="Little Atoms"/>
</outline> </outline>
<outline text="RSS Guard" description="News and updates on RSS Guard."> <outline description="News and updates on RSS Guard." rssguard:icon="AAAAIgBRAFAAaQB4AG0AYQBwAEkAYwBvAG4ARQBuAGcAaQBuAGUAAAABAAAAAYlQTkcNChoKAAAADUlIRFIAAABAAAAAQAgGAAAAqmlx3gAAAAlwSFlzAAAOxAAADsQBlSsOGwAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxMS0wNy0yOVQxNToxOTo1MCswMzowMMnGKbgAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTEtMDctMjlUMTU6MTg6MzcrMDM6MDBUkc0zAAAHS0lEQVR4nO1bT28bxxV/b2ZIkRQlyvTCksJDaUcGYhCxWx19aA492EC/QQ4NkPRD9NQPULTfoB+g95x8yDFABMhIrISHoor/RDbV6J9FVaRl7s57PWiXHg5nlqTsiMskP2BB7u78ee/N+zscAvyKXzZwjPc4RjsbbFyZRhpjcnl5ubCwsFC6devW1UKhkJtgXP348eO9hw8fHgNA9JY0/qRQnuciCILS0tJScPfu3Y+r1eoniLgA460oMnN47dq1fyml/rGxsXEAAPrdkfxu4RRAo9FQe3t781euXPmgXC7/OYqiOvNk2pzP5z+7efPm5sbGxucAcAYZNQenADqdjpBSFpj5qta6EoYhTCoApVS1XC5/fOfOnS8fPXr0I0xHAAwAlNbAZwKQz+cFM4soioCZJxYAEUEul/tofX39T7dv3/43M0/qSC8MIjpttVrfb21t7a2urp41m80QPAvgFUACrTVofTETZualQqHwV2YOLzTAxRGVSqVvy+Xy3zc3N79aW1s72d7efu1q6BVAvGKYCGBSDQA4F16v1ysgYmHizm8JpdTvq9VqtLKy8pejo6NtOI9GQyuZqgExAxBFmY5kQ2BmEEJALpf7UEpZ73Q6rUaj0Wk2m2MJQD59+lSur6/PLy4uVplZEKX6kUxCaw1CiHylUqnVarUrW1tbL+FcAwaEYDumXK1WW7x3794flpaWPlNK/RYAAmYWvokQL823OZFmmohIAHBARN+8fPnynw8ePPji+fPn/wOAvk+SRvvcwsLC4v379/+4srLyNynl74honojQjALJd9f9NK4RNCEAzEsp3y+VSneDIPjhyZMnP/R6vQji8JiYAFar1eL169d/EwTBp1rrWq/Xc0l0QOrTXv0ENj0urcjn87VqtfrpjRs3vtvZ2fn+6OgoAoC+aispZalQKNQR8YMwdEctc+CsMA8wSIvPJMIwBCnlrXK5fF1KWYJ48QUAQL1el0KIotZ6kZnnXIMgYn8i89O8LguueW2abDAzENEcMy8KIYr1el0CxFKIogiVUjkAUK6sDxGdq3+R3OBdwDev/dx1T0RKKZWLoggBYg2IHR26vL0tzSypvo1xaGVmwcxIRAjgyAPGWdVprfwojFocF90DAtBao9nQVP1Ran/ZmuGiw3zm+o6IfR4TmCqPQgj0DeLDZTvASee1+RFCDGzxmRrASdFja4DLCZpJx7T8go8m+735PK5s+w9MAXg3P11MZsEZptGQor3DGrC6ugoHBwdDAjAZz6rjMzHKL8TAXC6HQRBAq9U6F8Du7i4opZJQiGlO0DdR1uDxZX0ed3d3AWDQCaZ1HDnJtDAJjSPDIBgmMC5zWRWC7QANDfaHQbtzFhzd28Ljw5xhEEz7Nzu5Qow5+LQxSW3A1u60AAAIggDjF/3ND3uDwTdBFq405h1tkZkxCII3xVDcMBHCRFLOItJotfkcMAE7FfapftaRVhbHqfCb+1Gdfe9GqeBlwEXDuPQncFaDrg5pGWEWtCRt1U3YPNq1wJCXnKVU2AVLOxLe+jwKgHOpJFHA7jirjAN4eUBmxkQTnJmgXer6coBplsIJ0mhM3pufYGWCQ4kQEYEQ3h+C0gaeGsalgYiGTNzlA5wZoKsazEKYHKdiTdOC1Dxg1qrBUbQzsz8PSFTDZ9NZYHZc+Gg1IppbAwAAiWhACLO2EWLDpDn+md9fDieScWV89vcsIo1W47l3V7jf0BXizOdZFoJvd9jnsIdMIAmFLmQh7o+Ci3ajZhja+B15Ssw12M8Jzh2hNCZtDZi2QMahx/ILw04wiqKhWsDuaD6bNtMupDg9uykyMyY/j49lAj6nmAX4VnxcX9UXgFIKkwNR5iCTZIZZgk13wgsRoVJqsBwGAIjPBA+dCJt12HlBrP7996km8HMRQJo5DJhA0sGl9lmP/zbSHKJpAn0BxEfjJt4Wn7ZgLqClaB4DVADnW2JKKcHxIalJBp01M2FmoZQSyZbYwNYPIrK+6J8DZgBaa42IAysmAADa7TZJKXtnZ2edbrd7ZO4EZzXxGQWbdkSEbrd72O12O1LKXrvdfnNWeH5+Poqi6JSZ91qt1qNisbg8Nzc37zoWM06S8VP5hXF2qHw0np2ddV68eLGltd4jotNKpRLu7++fnxY/Pj6mYrEopZS5brcrXr16JZRSJSGEBAAiIk1Empk1M+vknog0APSf+y5XG3hzdt87hjmn79Jaa5M+kzYi0mEY9k5OTvafPXu2eXh4+CUzfxeG4YudnZ1TAOAkClCxWDxh5h0i+vrg4KDXbrefKKWuCiEmrhgTvCtNeBsTJKIoiqLDMAz/AwBNIcROsVg8gfi4vEkhLi8vl0qlUtDr9d4TQiwDwBIzT/KP0cwBEUMAOCai/+bz+d3Xr1/vt1qtVwDnR+XsJcJGo5Frt9tlIioLIfKc8m+RWQAiEhH1hBCnlUrltNlsDvwRwqejCABybW1NJmXjrEIpxdvb24mvGbKl/wN0m61UhnmYzwAAAABJRU5ErkJgggAAALAAQwA6AC8AVQBzAGUAcgBzAC8AcgBvAHQAdABlAHIALwBEAG8AYwB1AG0AZQBuAHQAcwAvAFAAcgBvAGoAZQBrAHQAeQAvAHIAcwBzAGcAdQBhAHIAZAAtAGIAdQBpAGwAZAAvAGkAYwBvAG4AcwAvAG0AaQBuAGkALQBrAGYAYQBlAG4AegBhAC8AZgBvAGwAZABlAHIALQBjAGEAdABlAGcAbwByAHkALgBwAG4AZwAAAEAAAABAAAAAAAAAAAE=" text="RSS Guard">
<outline xmlUrl="http://bitbucket.org/skunkos/rssguard/rss" text="Recent Commits" version="RSS" description="Recent commits for RSS Guard project." encoding="UTF-8" title="Recent Commits"/> <outline xmlUrl="http://bitbucket.org/skunkos/rssguard/rss" description="Recent commits for RSS Guard project." encoding="UTF-8" rssguard:icon="AAAAIgBRAFAAaQB4AG0AYQBwAEkAYwBvAG4ARQBuAGcAaQBuAGUAAAABAAAAAYlQTkcNChoKAAAADUlIRFIAAAAQAAAAEAgGAAAAH/P/YQAAAAlwSFlzAAAOxAAADsQBlSsOGwAAApdJREFUOI1lUl1IU3EU//3vrnPD3eXWLMiPTQOHJn3oImahY+mTHwX10EuUDyVRaI8VK6Qekp7SkqBe9CHrYUngKCqTKRTzgwxdiYRtGhqK3oXb0Ll777+H7V6u7sCBwznn9zu/c/5/ApVVtA22s3rOtbW+UCJsblik5BYHAEyWLsrqjWu6vdbfwmbUH+xu6pIxBABqe2nboq+zC5II85GGV4m1hYDJcSbACkgAgMAiOzLx1qm1FDkjMx/OgRC2qPFW+8hl0s0CwPJQj4cK29DkmP6KMf5j8MnZXmTaeOWdL+us3ngyGVsvWB7q8QDoJgBw6OagPx7+VgsAhNGktRGAMKmYSgCl6VAEAOTYKkd+PG5yMQCgMxWsymOoJKZcFECF7ZSLgpKXTcYwABBfnAkqk5XrMDCV13lN5XVeRYlS0iC+OBNUCPafuvh+N9jW7HHmllZ35JZWd9iaPc7dJDKGAYCRFjKhLmq5vJC/hQTCvs5g2NcZ9LeQQBZnCat7ZAwrJxi9cU2MRywAkIzzhQDAlZx4J9eFeKRA3SvHCsEea9UYPzvcACqBiknW3to/Nf3IfQwA7K39U4mVX6y83h5r1ZiyrVrW8QfB+/zs5xvSVtSUGpU+bPr6jI6LmMtOP524W3EvQ4G7j+avjL85ON/fbgYA13PauDr5+jAA7HNcmPZfJT4A0F33vnT30fzhS2QpQ0Hx+YcUVILB5vj0b270j9nu+g4A/Jz/aK69pjAWnqwHYRDy3iYZCgBAa8wLJfil4uh8oJ7V6rERSq3KavWIzgcAANnm/JAas+NxDVbHANGkOJUfqfqBRMPCYHUMqDE7VgCAmhfUHQ19vRZf/lkmJmJmANBkG/icA+WzXHH1s9ErZFjd/x/h2QrkdqsYGwAAAABJRU5ErkJggv////8AAAAQAAAAEAAAAAAAAAAB" title="Recent Commits" version="RSS" text="Recent Commits"/>
</outline> </outline>
</body> </body>
</opml> </opml>

View file

@ -2,6 +2,9 @@
<center><h2>2.4.0</h2></center> <center><h2>2.4.0</h2></center>
Added: Added:
<ul> <ul>
<li>RSS Guard is now able to export/import feed/category icons to/from OPML 2.0 files.</li>
<li>Localizations now load their titles for localization list automatically.</li>
<li>All feeds are by default checked when exporting/importing them.</li>
<li>Message previewer now displays MIME type of all podcasts too. This MIME type is also stored in DB.</li> <li>Message previewer now displays MIME type of all podcasts too. This MIME type is also stored in DB.</li>
<li>Ability to fetch only new icon for feed from its online source.</li> <li>Ability to fetch only new icon for feed from its online source.</li>
<li>Option to search highlighted text in web browser via Google, available from context menu. (issue #72)</li> <li>Option to search highlighted text in web browser via Google, available from context menu. (issue #72)</li>
@ -9,6 +12,7 @@ Added:
Fixed: Fixed:
<ul> <ul>
<li>Reworked DB initialization scripts.</li>
<li>Titles and descriptions of feeds are now fetched correctly in feed add/edit dialog.</li> <li>Titles and descriptions of feeds are now fetched correctly in feed add/edit dialog.</li>
</ul> </ul>

View file

@ -103,6 +103,7 @@ bool FeedsImportExportModel::exportToOMPL20(QByteArray &result) {
QDomElement outline_category = opml_document.createElement("outline"); QDomElement outline_category = opml_document.createElement("outline");
outline_category.setAttribute("text", child_item->title()); outline_category.setAttribute("text", child_item->title());
outline_category.setAttribute("description", child_item->description()); outline_category.setAttribute("description", child_item->description());
outline_category.setAttribute("rssguard:icon", QString(qApp->icons()->toByteArray(child_item->icon())));
active_element.appendChild(outline_category); active_element.appendChild(outline_category);
items_to_process.push(child_item); items_to_process.push(child_item);
elements_to_use.push(outline_category); elements_to_use.push(outline_category);
@ -117,6 +118,7 @@ bool FeedsImportExportModel::exportToOMPL20(QByteArray &result) {
outline_feed.setAttribute("description", child_feed->description()); outline_feed.setAttribute("description", child_feed->description());
outline_feed.setAttribute("encoding", child_feed->encoding()); outline_feed.setAttribute("encoding", child_feed->encoding());
outline_feed.setAttribute("title", child_feed->title()); outline_feed.setAttribute("title", child_feed->title());
outline_feed.setAttribute("rssguard:icon", QString(qApp->icons()->toByteArray(child_feed->icon())));
switch (child_feed->type()) { switch (child_feed->type()) {
case FeedsModelFeed::Rss0X: case FeedsModelFeed::Rss0X:
@ -188,6 +190,7 @@ bool FeedsImportExportModel::importAsOPML20(const QByteArray &data) {
QString feed_encoding = child_element.attribute("encoding", DEFAULT_FEED_ENCODING); QString feed_encoding = child_element.attribute("encoding", DEFAULT_FEED_ENCODING);
QString feed_type = child_element.attribute("version", DEFAULT_FEED_TYPE).toUpper(); QString feed_type = child_element.attribute("version", DEFAULT_FEED_TYPE).toUpper();
QString feed_description = child_element.attribute("description"); QString feed_description = child_element.attribute("description");
QIcon feed_icon = qApp->icons()->fromByteArray(child_element.attribute("rssguard:icon").toLocal8Bit());
FeedsModelFeed *new_feed = new FeedsModelFeed(active_model_item); FeedsModelFeed *new_feed = new FeedsModelFeed(active_model_item);
new_feed->setTitle(feed_title); new_feed->setTitle(feed_title);
@ -195,7 +198,7 @@ bool FeedsImportExportModel::importAsOPML20(const QByteArray &data) {
new_feed->setEncoding(feed_encoding); new_feed->setEncoding(feed_encoding);
new_feed->setUrl(feed_url); new_feed->setUrl(feed_url);
new_feed->setCreationDate(QDateTime::currentDateTime()); new_feed->setCreationDate(QDateTime::currentDateTime());
new_feed->setIcon(qApp->icons()->fromTheme("folder-feed")); new_feed->setIcon(feed_icon.isNull() ? qApp->icons()->fromTheme("folder-feed") : feed_icon);
new_feed->setAutoUpdateType(FeedsModelFeed::DefaultAutoUpdate); new_feed->setAutoUpdateType(FeedsModelFeed::DefaultAutoUpdate);
if (feed_type == "RSS1") { if (feed_type == "RSS1") {
@ -215,6 +218,7 @@ bool FeedsImportExportModel::importAsOPML20(const QByteArray &data) {
// Add category and continue. // Add category and continue.
QString category_title = child_element.attribute("text"); QString category_title = child_element.attribute("text");
QString category_description = child_element.attribute("description"); QString category_description = child_element.attribute("description");
QIcon category_icon = qApp->icons()->fromByteArray(child_element.attribute("rssguard:icon").toLocal8Bit());
if (category_title.isEmpty()) { if (category_title.isEmpty()) {
qWarning("Given OMPL file provided category without valid text attribute. Using fallback name."); qWarning("Given OMPL file provided category without valid text attribute. Using fallback name.");
@ -228,7 +232,7 @@ bool FeedsImportExportModel::importAsOPML20(const QByteArray &data) {
FeedsModelCategory *new_category = new FeedsModelCategory(active_model_item); FeedsModelCategory *new_category = new FeedsModelCategory(active_model_item);
new_category->setTitle(category_title); new_category->setTitle(category_title);
new_category->setIcon(qApp->icons()->fromTheme("folder-category")); new_category->setIcon(category_icon.isNull() ? qApp->icons()->fromTheme("folder-category") : category_icon);
new_category->setCreationDate(QDateTime::currentDateTime()); new_category->setCreationDate(QDateTime::currentDateTime());
new_category->setDescription(category_description); new_category->setDescription(category_description);
@ -260,14 +264,18 @@ void FeedsImportExportModel::setMode(const FeedsImportExportModel::Mode &mode) {
void FeedsImportExportModel::checkAllItems() { void FeedsImportExportModel::checkAllItems() {
foreach (FeedsModelRootItem *root_child, m_rootItem->childItems()) { foreach (FeedsModelRootItem *root_child, m_rootItem->childItems()) {
if (root_child->kind() != FeedsModelRootItem::RecycleBin) {
setData(indexForItem(root_child), Qt::Checked, Qt::CheckStateRole); setData(indexForItem(root_child), Qt::Checked, Qt::CheckStateRole);
} }
}
} }
void FeedsImportExportModel::uncheckAllItems() { void FeedsImportExportModel::uncheckAllItems() {
foreach (FeedsModelRootItem *root_child, m_rootItem->childItems()) { foreach (FeedsModelRootItem *root_child, m_rootItem->childItems()) {
if (root_child->kind() != FeedsModelRootItem::RecycleBin) {
setData(indexForItem(root_child), Qt::Unchecked, Qt::CheckStateRole); setData(indexForItem(root_child), Qt::Unchecked, Qt::CheckStateRole);
} }
}
} }
QModelIndex FeedsImportExportModel::index(int row, int column, const QModelIndex &parent) const { QModelIndex FeedsImportExportModel::index(int row, int column, const QModelIndex &parent) const {
@ -373,6 +381,17 @@ QVariant FeedsImportExportModel::data(const QModelIndex &index, int role) const
return static_cast<int>(Qt::Unchecked); return static_cast<int>(Qt::Unchecked);
} }
} }
else if (role == Qt::DecorationRole) {
switch (item->kind()) {
case FeedsModelRootItem::Category:
case FeedsModelRootItem::RecycleBin:
case FeedsModelRootItem::Feed:
return item->icon();
default:
return QVariant();
}
}
else if (role == Qt::DisplayRole) { else if (role == Qt::DisplayRole) {
switch (item->kind()) { switch (item->kind()) {
case FeedsModelRootItem::Category: case FeedsModelRootItem::Category:

View file

@ -644,7 +644,7 @@ bool FeedsModel::mergeModel(FeedsImportExportModel *model, QString &output_messa
bool some_feed_category_error = false; bool some_feed_category_error = false;
// We are definitely about to add some new items into the model. // We are definitely about to add some new items into the model.
emit layoutAboutToBeChanged(); //emit layoutAboutToBeChanged();
// Iterate all new items we would like to merge into current model. // Iterate all new items we would like to merge into current model.
while (!new_parents.isEmpty()) { while (!new_parents.isEmpty()) {
@ -698,7 +698,7 @@ bool FeedsModel::mergeModel(FeedsImportExportModel *model, QString &output_messa
} }
// Changes are done now. Finalize the new model. // Changes are done now. Finalize the new model.
emit layoutChanged(); //emit layoutChanged();
if (some_feed_category_error) { if (some_feed_category_error) {
output_message = tr("Import successfull, but some feeds/categories were not imported due to error."); output_message = tr("Import successfull, but some feeds/categories were not imported due to error.");

View file

@ -83,6 +83,8 @@
#define DOWNLOADER_ICON_SIZE 48 #define DOWNLOADER_ICON_SIZE 48
#define GOOGLE_SEARCH_URL "https://www.google.com/search?q=%1&ie=utf-8&oe=utf-8" #define GOOGLE_SEARCH_URL "https://www.google.com/search?q=%1&ie=utf-8&oe=utf-8"
#define FEED_INITIAL_OPML_PATTERN "feeds-%1.opml"
#define FEED_REGEX_MATCHER "<link[^>]+type=\\\"application/(atom|rss)\\+xml\\\"[^>]*>" #define FEED_REGEX_MATCHER "<link[^>]+type=\\\"application/(atom|rss)\\+xml\\\"[^>]*>"
#define FEED_HREF_REGEX_MATCHER "href\\=\\\"[^\\\"]+\\\"" #define FEED_HREF_REGEX_MATCHER "href\\=\\\"[^\\\"]+\\\""

View file

@ -0,0 +1,29 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2015 by Martin Rotter <rotter.martinos@gmail.com>
//
// RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#include "exceptions/applicationexception.h"
ApplicationException::ApplicationException(const QString &message) : m_message(message) {
}
ApplicationException::~ApplicationException() {
}
QString ApplicationException::message() const {
return m_message;
}

View file

@ -0,0 +1,35 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2015 by Martin Rotter <rotter.martinos@gmail.com>
//
// RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#ifndef APPLICATIONEXCEPTION_H
#define APPLICATIONEXCEPTION_H
#include <QString>
class ApplicationException {
public:
explicit ApplicationException(const QString &message = QString());
virtual ~ApplicationException();
QString message() const;
private:
QString m_message;
};
#endif // APPLICATIONEXCEPTION_H

View file

@ -0,0 +1,25 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2015 by Martin Rotter <rotter.martinos@gmail.com>
//
// RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#include "exceptions/ioexception.h"
IOException::IOException(const QString &message) : ApplicationException(message) {
}
IOException::~IOException() {
}

View file

@ -0,0 +1,14 @@
#ifndef IOEXCEPTION_H
#define IOEXCEPTION_H
#include "exceptions/applicationexception.h"
class IOException : public ApplicationException
{
public:
explicit IOException(const QString &message = QString());
virtual ~IOException();
};
#endif // IOEXCEPTION_H

View file

@ -25,6 +25,7 @@
#include "core/feeddownloader.h" #include "core/feeddownloader.h"
#include "core/feedsmodelfeed.h" #include "core/feedsmodelfeed.h"
#include "core/feedsselection.h" #include "core/feedsselection.h"
#include "core/feedsimportexportmodel.h"
#include "network-web/webbrowser.h" #include "network-web/webbrowser.h"
#include "gui/formmain.h" #include "gui/formmain.h"
#include "gui/messagesview.h" #include "gui/messagesview.h"
@ -34,6 +35,7 @@
#include "gui/messagebox.h" #include "gui/messagebox.h"
#include "gui/messagestoolbar.h" #include "gui/messagestoolbar.h"
#include "gui/feedstoolbar.h" #include "gui/feedstoolbar.h"
#include <exceptions/applicationexception.h>
#include <QVBoxLayout> #include <QVBoxLayout>
#include <QSplitter> #include <QSplitter>
@ -134,6 +136,34 @@ void FeedMessageViewer::quit() {
} }
} }
void FeedMessageViewer::loadInitialFeeds() {
QString target_opml_file = APP_INITIAL_FEEDS_PATH + QDir::separator() + FEED_INITIAL_OPML_PATTERN;
QString current_locale = qApp->localization()->loadedLanguage();
QString file_to_load;
if (QFile::exists(target_opml_file.arg(current_locale))) {
file_to_load = target_opml_file.arg(current_locale);
}
else if (QFile::exists(target_opml_file.arg(DEFAULT_LOCALE))) {
file_to_load = target_opml_file.arg(DEFAULT_LOCALE);
}
FeedsImportExportModel model;
QString output_msg;
try {
model.importAsOPML20(IOFactory::readTextFile(file_to_load));
model.checkAllItems();
if (m_feedsView->sourceModel()->mergeModel(&model, output_msg)) {
m_feedsView->expandAll();
}
}
catch (ApplicationException &ex) {
MessageBox::show(this, QMessageBox::Critical, tr("Error when loading initial feeds"), ex.message());
}
}
void FeedMessageViewer::switchMessageSplitterOrientation() { void FeedMessageViewer::switchMessageSplitterOrientation() {
if (m_messageSplitter->orientation() == Qt::Vertical) { if (m_messageSplitter->orientation() == Qt::Vertical) {
m_messageSplitter->setOrientation(Qt::Horizontal); m_messageSplitter->setOrientation(Qt::Horizontal);

View file

@ -83,6 +83,9 @@ class FeedMessageViewer : public TabContent {
} }
public slots: public slots:
void loadInitialFeeds();
// Switches orientation horizontal/vertical.
void switchMessageSplitterOrientation(); void switchMessageSplitterOrientation();
// Enables/disables main toolbars or list headers. // Enables/disables main toolbars or list headers.

View file

@ -19,6 +19,7 @@
#include "miscellaneous/application.h" #include "miscellaneous/application.h"
#include "miscellaneous/iconfactory.h" #include "miscellaneous/iconfactory.h"
#include "exceptions/applicationexception.h"
#include <QDialogButtonBox> #include <QDialogButtonBox>
#include <QPushButton> #include <QPushButton>

View file

@ -54,12 +54,13 @@ void FormImportExport::setMode(const FeedsImportExportModel::Mode &mode) {
switch (mode) { switch (mode) {
case FeedsImportExportModel::Export: { case FeedsImportExportModel::Export: {
m_model->setRootItem(qApp->mainForm()->tabWidget()->feedMessageViewer()->feedsView()->sourceModel()->rootItem()); m_model->setRootItem(qApp->mainForm()->tabWidget()->feedMessageViewer()->feedsView()->sourceModel()->rootItem());
m_model->checkAllItems();
m_ui->m_treeFeeds->setModel(m_model); m_ui->m_treeFeeds->setModel(m_model);
m_ui->m_treeFeeds->expandAll(); m_ui->m_treeFeeds->expandAll();
setWindowTitle(tr("Export feeds"));
setWindowIcon(qApp->icons()->fromTheme("document-export"));
m_ui->m_groupFile->setTitle(tr("Destination file")); m_ui->m_groupFile->setTitle(tr("Destination file"));
m_ui->m_groupFeeds->setTitle(tr("Source feeds && categories")); m_ui->m_groupFeeds->setTitle(tr("Source feeds && categories"));
setWindowTitle(tr("Export feeds"));
setWindowIcon(qApp->icons()->fromTheme("document-export"));
break; break;
} }
@ -143,6 +144,7 @@ void FormImportExport::selectImportFile() {
m_ui->m_lblSelectFile->setStatus(WidgetWithStatus::Ok, QDir::toNativeSeparators(selected_file), tr("File is selected.")); m_ui->m_lblSelectFile->setStatus(WidgetWithStatus::Ok, QDir::toNativeSeparators(selected_file), tr("File is selected."));
parseImportFile(selected_file); parseImportFile(selected_file);
m_model->checkAllItems();
} }
} }

View file

@ -20,6 +20,7 @@
#include "gui/messagebox.h" #include "gui/messagebox.h"
#include "gui/formmain.h" #include "gui/formmain.h"
#include "miscellaneous/iconfactory.h" #include "miscellaneous/iconfactory.h"
#include "exceptions/applicationexception.h"
#include "QFileDialog" #include "QFileDialog"

View file

@ -75,8 +75,7 @@ FormSettings::FormSettings(QWidget *parent) : QDialog(parent), m_ui(new Ui::Form
<< /*: Language column of language list. */ tr("Language") << /*: Language column of language list. */ tr("Language")
<< /*: Lang. code column of language list. */ tr("Code") << /*: Lang. code column of language list. */ tr("Code")
<< tr("Version") << tr("Version")
<< tr("Author") << tr("Author"));
<< tr("Email"));
m_ui->m_treeSkins->setColumnCount(4); m_ui->m_treeSkins->setColumnCount(4);
m_ui->m_treeSkins->setHeaderHidden(false); m_ui->m_treeSkins->setHeaderHidden(false);
@ -468,7 +467,6 @@ void FormSettings::loadLanguage() {
item->setText(1, language.m_code); item->setText(1, language.m_code);
item->setText(2, language.m_version); item->setText(2, language.m_version);
item->setText(3, language.m_author); item->setText(3, language.m_author);
item->setText(4, language.m_email);
item->setIcon(0, qApp->icons()->fromTheme(QString(FLAG_ICON_SUBFOLDER) + QDir::separator() + language.m_code)); item->setIcon(0, qApp->icons()->fromTheme(QString(FLAG_ICON_SUBFOLDER) + QDir::separator() + language.m_code));
} }

View file

@ -88,7 +88,7 @@
<item row="0" column="1"> <item row="0" column="1">
<widget class="QStackedWidget" name="m_stackedSettings"> <widget class="QStackedWidget" name="m_stackedSettings">
<property name="currentIndex"> <property name="currentIndex">
<number>5</number> <number>4</number>
</property> </property>
<widget class="QWidget" name="m_pageGeneral"> <widget class="QWidget" name="m_pageGeneral">
<layout class="QFormLayout" name="formLayout_5"> <layout class="QFormLayout" name="formLayout_5">

View file

@ -24,6 +24,7 @@
#include "gui/formmain.h" #include "gui/formmain.h"
#include "gui/feedmessageviewer.h" #include "gui/feedmessageviewer.h"
#include "gui/feedsview.h" #include "gui/feedsview.h"
#include "gui/messagebox.h"
#include "network-web/silentnetworkaccessmanager.h" #include "network-web/silentnetworkaccessmanager.h"
// Needed for setting ini file format on Mac OS. // Needed for setting ini file format on Mac OS.
@ -38,8 +39,6 @@
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
//: Name of language, e.g. English.
QObject::tr("LANG_NAME");
//: Abbreviation of language, e.g. en. //: Abbreviation of language, e.g. en.
//: Use ISO 639-1 code here combined with ISO 3166-1 (alpha-2) code. //: Use ISO 639-1 code here combined with ISO 3166-1 (alpha-2) code.
//: Examples: "cs_CZ", "en_GB", "en_US". //: Examples: "cs_CZ", "en_GB", "en_US".
@ -48,8 +47,6 @@ int main(int argc, char *argv[]) {
QObject::tr("LANG_VERSION"); QObject::tr("LANG_VERSION");
//: Name of translator - optional. //: Name of translator - optional.
QObject::tr("LANG_AUTHOR"); QObject::tr("LANG_AUTHOR");
//: Email of translator - optional.
QObject::tr("LANG_EMAIL");
// Ensure that ini format is used as application settings storage on Mac OS. // Ensure that ini format is used as application settings storage on Mac OS.
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
@ -108,6 +105,18 @@ int main(int argc, char *argv[]) {
else { else {
qDebug("Showing the main window when the application is starting."); qDebug("Showing the main window when the application is starting.");
main_window.show(); main_window.show();
if (qApp->settings()->value(GROUP(General), SETTING(General::FirstRun)).toBool()) {
// This is the first time user runs this application.
qApp->settings()->setValue(GROUP(General), General::FirstRun, false);
if (MessageBox::show(&main_window, QMessageBox::Question, QObject::tr("Load initial feeds"),
QObject::tr("Your started %1 for the first time, now you can load initial set of feeds.").arg(APP_NAME),
QObject::tr("Do you want to load initial set of feeds?"),
QString(), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
qApp->mainForm()->tabWidget()->feedMessageViewer()->loadInitialFeeds();
}
}
} }
// Display tray icon if it is enabled and available. // Display tray icon if it is enabled and available.

View file

@ -24,6 +24,7 @@
#include "gui/messagebox.h" #include "gui/messagebox.h"
#include "gui/formmain.h" #include "gui/formmain.h"
#include "gui/statusbar.h" #include "gui/statusbar.h"
#include "exceptions/applicationexception.h"
#include <QSessionManager> #include <QSessionManager>
#include <QThread> #include <QThread>
@ -242,13 +243,3 @@ void Application::restart() {
m_shouldRestart = true; m_shouldRestart = true;
quit(); quit();
} }
ApplicationException::ApplicationException(const QString &message) : m_message(message) {
}
ApplicationException::~ApplicationException() {
}
QString ApplicationException::message() const {
return m_message;
}

View file

@ -45,17 +45,6 @@ class FormMain;
class IconFactory; class IconFactory;
class QAction; class QAction;
class ApplicationException {
public:
explicit ApplicationException(const QString &message = QString());
virtual ~ApplicationException();
QString message() const;
private:
QString m_message;
};
class Application : public QtSingleApplication { class Application : public QtSingleApplication {
Q_OBJECT Q_OBJECT

View file

@ -17,9 +17,12 @@
#include "miscellaneous/iofactory.h" #include "miscellaneous/iofactory.h"
#include <exceptions/ioexception.h>
#include <QDir> #include <QDir>
#include <QFileInfo> #include <QFileInfo>
#include <QFile> #include <QFile>
#include <QObject>
IOFactory::IOFactory() { IOFactory::IOFactory() {
@ -33,6 +36,20 @@ QString IOFactory::getSystemFolder(SYSTEM_FOLDER_ENUM::StandardLocation location
#endif #endif
} }
QByteArray IOFactory::readTextFile(const QString &file_path) {
QFile input_file(file_path);
QByteArray input_data;
if (input_file.open(QIODevice::Text | QIODevice::Unbuffered | QIODevice::ReadOnly)) {
input_data = input_file.readAll();
input_file.close();
return input_data;
}
else {
throw IOException(tr("Cannot open file '%s' for reading.").arg(QDir::toNativeSeparators(file_path)));
}
}
bool IOFactory::copyFile(const QString &source, const QString &destination) { bool IOFactory::copyFile(const QString &source, const QString &destination) {
if (QFile::exists(destination)) { if (QFile::exists(destination)) {
if (!QFile::remove(destination)) { if (!QFile::remove(destination)) {

View file

@ -19,6 +19,7 @@
#define IOFACTORY_H #define IOFACTORY_H
#include <QStringList> #include <QStringList>
#include <QCoreApplication>
#if QT_VERSION >= 0x050000 #if QT_VERSION >= 0x050000
#include <QStandardPaths> #include <QStandardPaths>
@ -30,6 +31,8 @@
class IOFactory { class IOFactory {
Q_DECLARE_TR_FUNCTIONS(IOFactory)
private: private:
IOFactory(); IOFactory();
@ -37,6 +40,8 @@ class IOFactory {
// Returns system-wide folder according to type. // Returns system-wide folder according to type.
static QString getSystemFolder(SYSTEM_FOLDER_ENUM::StandardLocation location); static QString getSystemFolder(SYSTEM_FOLDER_ENUM::StandardLocation location);
static QByteArray readTextFile(const QString &file_path);
// Copies file, overwrites destination. // Copies file, overwrites destination.
static bool copyFile(const QString &source, const QString &destination); static bool copyFile(const QString &source, const QString &destination);

View file

@ -74,11 +74,11 @@ QList<Language> Localization::installedLanguages() {
QDir::Name)) { QDir::Name)) {
if (translator.load(file.absoluteFilePath())) { if (translator.load(file.absoluteFilePath())) {
Language new_language; Language new_language;
new_language.m_name = translator.translate("QObject", "LANG_NAME");
new_language.m_code = translator.translate("QObject", "LANG_ABBREV"); new_language.m_code = translator.translate("QObject", "LANG_ABBREV");
new_language.m_version = translator.translate("QObject", "LANG_VERSION"); new_language.m_version = translator.translate("QObject", "LANG_VERSION");
new_language.m_author = translator.translate("QObject", "LANG_AUTHOR"); new_language.m_author = translator.translate("QObject", "LANG_AUTHOR");
new_language.m_email = translator.translate("QObject", "LANG_EMAIL"); new_language.m_email = translator.translate("QObject", "LANG_EMAIL");
new_language.m_name = QLocale(new_language.m_code).nativeLanguageName();
languages << new_language; languages << new_language;
} }