diff --git a/data/pref.xml b/data/pref.xml
index 2b7c0a372..1683000f3 100644
--- a/data/pref.xml
+++ b/data/pref.xml
@@ -76,6 +76,9 @@
+
diff --git a/src/app/ui/news_listbox.cpp b/src/app/ui/news_listbox.cpp
index b146ffac2..2cd8f4a3d 100644
--- a/src/app/ui/news_listbox.cpp
+++ b/src/app/ui/news_listbox.cpp
@@ -11,11 +11,15 @@
#include "app/ui/news_listbox.h"
+#include "app/app.h"
+#include "app/pref/preferences.h"
#include "app/res/http_loader.h"
#include "app/ui/skin/skin_theme.h"
#include "app/ui/skin/style.h"
#include "app/xml_document.h"
+#include "base/fs.h"
#include "base/string.h"
+#include "base/time.h"
#include "ui/link_label.h"
#include "ui/paint_event.h"
#include "ui/preferred_size_event.h"
@@ -182,7 +186,12 @@ NewsListBox::NewsListBox()
, m_timer(250, this)
{
m_timer.Tick.connect(&NewsListBox::onTick, this);
- reload();
+
+ std::string cache = App::instance()->preferences().news.cacheFile();
+ if (!cache.empty() && base::is_file(cache) && validCache(cache))
+ parseFile(cache);
+ else
+ reload();
}
NewsListBox::~NewsListBox()
@@ -227,13 +236,21 @@ void NewsListBox::onTick()
return;
}
+ parseFile(fn);
+}
+
+void NewsListBox::parseFile(const std::string& filename)
+{
+ View* view = View::getView(this);
+
XmlDocumentRef doc;
try {
- doc = open_xml(fn);
+ doc = open_xml(filename);
}
catch (...) {
addChild(new ProblemsItem());
- View::getView(this)->updateView();
+ if (view)
+ view->updateView();
return;
}
@@ -270,7 +287,23 @@ void NewsListBox::onTick()
if (linkXml)
addChild(new NewsItem(linkXml->GetText(), "More...", ""));
- View::getView(this)->updateView();
+ if (view)
+ view->updateView();
+
+ // Save as cached news
+ App::instance()->preferences().news.cacheFile(filename);
+}
+
+bool NewsListBox::validCache(const std::string& filename)
+{
+ base::Time
+ now = base::current_time(),
+ time = base::get_modification_time(filename);
+
+ now.dateOnly();
+ time.dateOnly();
+
+ return (now == time);
}
} // namespace app
diff --git a/src/app/ui/news_listbox.h b/src/app/ui/news_listbox.h
index 5397c442c..16e0645da 100644
--- a/src/app/ui/news_listbox.h
+++ b/src/app/ui/news_listbox.h
@@ -12,6 +12,8 @@
#include "ui/listbox.h"
#include "ui/timer.h"
+#include
+
namespace app {
class HttpLoader;
@@ -25,6 +27,8 @@ namespace app {
private:
void onTick();
+ void parseFile(const std::string& filename);
+ bool validCache(const std::string& filename);
ui::Timer m_timer;
HttpLoader* m_loader;
diff --git a/src/base/CMakeLists.txt b/src/base/CMakeLists.txt
index 7a9393116..d1b3ffc36 100644
--- a/src/base/CMakeLists.txt
+++ b/src/base/CMakeLists.txt
@@ -1,5 +1,5 @@
# Aseprite Base Library
-# Copyright (c) 2001-2014 David Capello
+# Copyright (c) 2001-2015 David Capello
include(CheckCSourceCompiles)
include(CheckCXXSourceCompiles)
@@ -65,6 +65,7 @@ set(BASE_SOURCES
system_console.cpp
temp_dir.cpp
thread.cpp
+ time.cpp
trim_string.cpp
version.cpp)
diff --git a/src/base/fs.h b/src/base/fs.h
index 3bbb2c79b..4b66754ad 100644
--- a/src/base/fs.h
+++ b/src/base/fs.h
@@ -1,5 +1,5 @@
// Aseprite Base Library
-// Copyright (c) 2001-2013 David Capello
+// Copyright (c) 2001-2013, 2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
@@ -12,6 +12,8 @@
namespace base {
+ class Time;
+
bool is_file(const std::string& path);
bool is_directory(const std::string& path);
@@ -23,6 +25,8 @@ namespace base {
bool has_readonly_attr(const std::string& path);
void remove_readonly_attr(const std::string& path);
+ Time get_modification_time(const std::string& path);
+
void make_directory(const std::string& path);
void make_all_directories(const std::string& path);
void remove_directory(const std::string& path);
diff --git a/src/base/fs_unix.h b/src/base/fs_unix.h
index 6ecb157c1..4964b3b82 100644
--- a/src/base/fs_unix.h
+++ b/src/base/fs_unix.h
@@ -1,5 +1,5 @@
// Aseprite Base Library
-// Copyright (c) 2001-2013 David Capello
+// Copyright (c) 2001-2013, 2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
@@ -82,6 +82,19 @@ void remove_readonly_attr(const std::string& path)
}
}
+Time get_modification_time(const std::string& path)
+{
+ struct stat sts;
+ int result = stat(path.c_str(), &sts);
+ if (result != 0)
+ return Time();
+
+ struct tm* t = localtime(&sts.st_mtime);
+ return Time(
+ t->tm_year+1900, t->tm_mon+1, t->tm_mday,
+ t->tm_hour, t->tm_min, t->tm_sec);
+}
+
void remove_directory(const std::string& path)
{
int result = rmdir(path.c_str());
diff --git a/src/base/fs_win32.h b/src/base/fs_win32.h
index 20a82ce6b..9b55afd29 100644
--- a/src/base/fs_win32.h
+++ b/src/base/fs_win32.h
@@ -1,5 +1,5 @@
// Aseprite Base Library
-// Copyright (c) 2001-2013 David Capello
+// Copyright (c) 2001-2013, 2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
@@ -12,6 +12,7 @@
#include "base/path.h"
#include "base/string.h"
#include "base/win32_exception.h"
+#include "base/time.h"
namespace base {
@@ -68,6 +69,24 @@ void remove_readonly_attr(const std::string& path)
::SetFileAttributes(fn.c_str(), attr & ~FILE_ATTRIBUTE_READONLY);
}
+Time get_modification_time(const std::string& path)
+{
+ WIN32_FILE_ATTRIBUTE_DATA data;
+ ZeroMemory(&data, sizeof(data));
+
+ std::wstring fn = from_utf8(path);
+ if (!GetFileAttributesEx(fn.c_str(), GetFileExInfoStandard, (LPVOID)&data))
+ return Time();
+
+ SYSTEMTIME utc, local;
+ FileTimeToSystemTime(&data.ftLastWriteTime, &utc);
+ SystemTimeToTzSpecificLocalTime(NULL, &utc, &local);
+
+ return Time(
+ local.wYear, local.wMonth, local.wDay,
+ local.wHour, local.wMinute, local.wSecond);
+}
+
void make_directory(const std::string& path)
{
BOOL result = ::CreateDirectory(from_utf8(path).c_str(), NULL);
diff --git a/src/base/time.cpp b/src/base/time.cpp
new file mode 100644
index 000000000..ac4a0a78f
--- /dev/null
+++ b/src/base/time.cpp
@@ -0,0 +1,40 @@
+// Aseprite Base Library
+// Copyright (c) 2001-2013, 2015 David Capello
+//
+// This file is released under the terms of the MIT license.
+// Read LICENSE.txt for more information.
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "base/time.h"
+
+#if _WIN32
+ #include
+#else
+ #include
+#endif
+
+namespace base {
+
+Time current_time()
+{
+#if _WIN32
+
+ SYSTEMTIME st;
+ GetLocalTime(&st);
+ return Time(st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
+
+#else
+
+ std::time_t now = std::time(nullptr);
+ struct tm* t = std::time(nullptr);
+ return Time(
+ t->tm_year+1900, t->tm_mon+1, t->tm_mday,
+ t->tm_hour, t->tm_min, t->tm_sec);
+
+#endif
+}
+
+} // namespace base
diff --git a/src/base/time.h b/src/base/time.h
new file mode 100644
index 000000000..85235bb92
--- /dev/null
+++ b/src/base/time.h
@@ -0,0 +1,53 @@
+// Aseprite Base Library
+// Copyright (c) 2001-2013, 2015 David Capello
+//
+// This file is released under the terms of the MIT license.
+// Read LICENSE.txt for more information.
+
+#ifndef BASE_TIME_H_INCLUDED
+#define BASE_TIME_H_INCLUDED
+#pragma once
+
+#include
+
+namespace base {
+
+ class Time {
+ public:
+ int year, month, day;
+ int hour, minute, second;
+
+ Time(int year = 0, int month = 0, int day = 0,
+ int hour = 0, int minute = 0, int second = 0)
+ : year(year), month(month), day(day)
+ , hour(hour), minute(minute), second(second) {
+ }
+
+ bool valid() const {
+ return (year != 0 && month != 0 && day != 0);
+ }
+
+ void dateOnly() {
+ hour = minute = second = 0;
+ }
+
+ bool operator==(const Time& other) {
+ return
+ year == other.year &&
+ month == other.month &&
+ day == other.day &&
+ hour == other.hour &&
+ minute == other.minute &&
+ second == other.second;
+ }
+
+ bool operator!=(const Time& other) {
+ return !operator==(other);
+ }
+ };
+
+ Time current_time();
+
+}
+
+#endif