1 //===========================================
2 // Lumina-DE source code
3 // Copyright (c) 2012-2015, Ken Moore
4 // Available under the 3-clause BSD license
5 // See the LICENSE file for full details
6 //===========================================
7 #include "LClock.h"
8 #include "LSession.h"
9 #include <LuminaThemes.h>
10 #include <LuminaXDG.h>
11
LClock(QWidget * parent,QString id,bool horizontal)12 LClock::LClock(QWidget *parent, QString id, bool horizontal) : LPPlugin(parent, id, horizontal){
13 button = new QToolButton(this); //RotateToolButton(this);
14 button->setAutoRaise(true);
15 button->setToolButtonStyle(Qt::ToolButtonTextOnly);
16 button->setStyleSheet("font-weight: bold;");
17 button->setPopupMode(QToolButton::DelayedPopup); //make sure it runs the update routine first
18 button->setMenu(new QMenu());
19 //button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
20 //this->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
21 connect(button, SIGNAL(clicked()), this, SLOT(openMenu()));
22 connect(button->menu(), SIGNAL(aboutToHide()), this, SIGNAL(MenuClosed()));
23 calendar = new QCalendarWidget(this);
24 calAct = new QWidgetAction(this);
25 calAct->setDefaultWidget(calendar);
26 TZMenu = new QMenu(this);
27 connect(TZMenu, SIGNAL(triggered(QAction*)), this, SLOT(ChangeTZ(QAction*)) );
28
29 //Now assemble the menu
30 button->menu()->addAction(calAct);
31 button->menu()->addMenu(TZMenu);
32
33 this->layout()->setContentsMargins(0,0,0,0); //reserve some space on left/right
34 this->layout()->addWidget(button);
35
36 //Setup the timer
37 timer = new QTimer();
38 //Load all the initial settings
39 updateFormats();
40 LocaleChange();
41 ThemeChange();
42 OrientationChange();
43 //Now connect/start the timer
44 connect(timer,SIGNAL(timeout()), this, SLOT(updateTime()) );
45 connect(QApplication::instance(), SIGNAL(SessionConfigChanged()), this, SLOT(updateFormats()) );
46 timer->start();
47 }
48
~LClock()49 LClock::~LClock(){
50 timer->stop();
51 delete timer;
52 }
53
54
updateTime(bool adjustformat)55 void LClock::updateTime(bool adjustformat){
56 QDateTime CT = QDateTime::currentDateTime();
57 //Now update the display
58 QString label;
59 QString timelabel;
60 QString datelabel;
61 if(deftime){ timelabel = CT.time().toString(Qt::DefaultLocaleShortDate) ; }
62 else{ timelabel=CT.toString(timefmt); }
63 if(defdate){ datelabel = CT.date().toString(Qt::DefaultLocaleShortDate); }
64 else{ datelabel = CT.toString(datefmt); }
65 if(datetimeorder == "dateonly"){
66 label = datelabel;
67 button->setToolTip(timelabel);
68 }else if(datetimeorder == "timedate"){
69 label = timelabel + "\n" + datelabel;
70 button->setToolTip("");
71 }else if(datetimeorder == "datetime"){
72 label = datelabel + "\n" + timelabel;
73 button->setToolTip("");
74 }else{
75 label = timelabel;
76 button->setToolTip(datelabel);
77 }
78 QStringList lines = label.split("\n");
79 if( this->layout()->direction() == QBoxLayout::TopToBottom ){
80 //different routine for vertical text (need newlines instead of spaces)
81 for(int i=0; i<label.count("\n")+1; i++){
82 if(this->size().width() < (this->fontMetrics().horizontalAdvance(label.section("\n",i,i))+10 )&& label.section("\n",i,i).contains(" ")){
83 label.replace(label.section("\n",i,i), label.section("\n",i,i).replace(" ", "\n"));
84 i--;
85 }
86 }
87 //label.replace(" ","\n");
88 }else if( this->size().height() < lines.length()*this->fontMetrics().height() ){
89 label.replace("\n",", ");
90 }
91 if(adjustformat){
92 QFont font = LSession::handle()->font();
93 font.setBold(true);
94 button->setFont(font);
95 //Check the font/spacing for the display and adjust as necessary
96 QStringList lines = label.split("\n");
97 QFontMetrics metrics(font);
98 if(this->layout()->direction()==QBoxLayout::LeftToRight){
99 //horizontal layout
100 int wid = 0;
101 int lwid = 0;
102 for(int i=0; i<lines.length(); i++){
103 lwid = metrics.horizontalAdvance(lines[i]);
104 if(lwid>wid){ wid = lwid; }
105 }
106 qDebug() << "Verify Clock width:" << lines.length() << wid << lines;
107 this->setMinimumWidth(wid);
108 this->setMaximumWidth(wid + (4*metrics.horizontalAdvance("O")));
109 }else{
110 //vertical layout
111 this->setMinimumHeight(metrics.lineSpacing() * lines.length());
112 this->setMaximumHeight( (lines.length()+4)*metrics.height() );
113 }
114 }
115 button->setText(label);
116 }
117
updateFormats()118 void LClock::updateFormats(){
119 qDebug() << "Updating clock format";
120 timefmt = LSession::handle()->sessionSettings()->value("TimeFormat","").toString();
121 datefmt = LSession::handle()->sessionSettings()->value("DateFormat","").toString();
122 deftime = timefmt.simplified().isEmpty();
123 defdate = datefmt.simplified().isEmpty();
124 //Adjust the timer interval based on the smallest unit displayed
125 if(deftime){ timer->setInterval(500); } //1/2 second
126 else if(timefmt.contains("z")){ timer->setInterval(1); } //every millisecond (smallest unit)
127 else if(timefmt.contains("s")){ timer->setInterval(500); } //1/2 second
128 else if(timefmt.contains("m")){ timer->setInterval(2000); } //2 seconds
129 else{ timer->setInterval(1000); } //unknown format - use 1 second interval
130 datetimeorder = LSession::handle()->sessionSettings()->value("DateTimeOrder", "timeonly").toString().toLower();
131 //this->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
132 updateTime(true);
133 //Now fix the size of the widget with the new size hint
134 //this->setFixedWidth( this->sizeHint().width() +6);
135 }
136
updateMenu()137 void LClock::updateMenu(){
138 QDateTime cdt = QDateTime::currentDateTime();
139 TZMenu->setTitle(QString(tr("Time Zone (%1)")).arg(cdt.timeZoneAbbreviation()) );
140 calendar->showToday(); //make sure the current month is visible
141 calendar->setSelectedDate(QDate::currentDate()); //select the actual date for today
142 }
143
openMenu()144 void LClock::openMenu(){
145 updateMenu();
146 button->showMenu();
147 }
148
closeMenu()149 void LClock::closeMenu(){
150 button->menu()->hide();
151 }
152
ChangeTZ(QAction * act)153 void LClock::ChangeTZ(QAction *act){
154 LTHEME::setCustomEnvSetting("TZ",act->whatsThis());
155 QTimer::singleShot(500, this, SLOT(updateTime()) );
156 }
157
LocaleChange()158 void LClock::LocaleChange(){
159 //Refresh all the time zone information
160 TZMenu->clear();
161 TZMenu->addAction(tr("Use System Time"));
162 TZMenu->addSeparator();
163 QList<QByteArray> TZList = QTimeZone::availableTimeZoneIds();
164 //Orgnize time zones for smaller menus (Continent/Country/City)
165 // Note: id = Continent/City
166 QStringList info;
167 for(int i=0; i<TZList.length(); i++){
168 QTimeZone tz(TZList[i]);
169 if(!QString(tz.id()).contains("/")){ continue; }
170 info << "::::"+QString(tz.id()).section("/",0,0)+"::::"+QLocale::countryToString(tz.country())+"::::"+QString(tz.id()).section("/",1,100).replace("_"," ")+"::::"+QString(tz.id());
171 }
172 //Now sort alphabetically
173 info.sort();
174 //Now create the menu tree
175 QString continent, country; //current continent/country
176 QMenu *tmpC=0; //continent menu
177 QMenu *tmpCM=0; //country menu
178 for(int i=0; i<info.length(); i++){
179 //Check if different continent
180 if(info[i].section("::::",1,1)!=continent){
181 if(tmpC!=0){
182 if(tmpCM!=0 && !tmpCM->isEmpty()){
183 tmpC->addMenu(tmpCM);
184 }
185 if(!tmpC->isEmpty()){ TZMenu->addMenu(tmpC); }
186 }
187 tmpC = new QMenu(this);
188 tmpC->setTitle(info[i].section("::::",1,1));
189 tmpCM = new QMenu(this);
190 tmpCM->setTitle(info[i].section("::::",2,2));
191 //Check if different country
192 }else if(info[i].section("::::",2,2)!=country){
193 if(tmpC!=0 && tmpCM!=0 && !tmpCM->isEmpty()){
194 tmpC->addMenu(tmpCM);
195 }
196 tmpCM = new QMenu(this);
197 tmpCM->setTitle(info[i].section("::::",2,2));
198 }
199 //Now create the entry within the country menu
200 if(tmpCM!=0){
201 QAction *act = new QAction(info[i].section("::::",3,3), this);
202 act->setWhatsThis(info[i].section("::::",4,4) );
203 tmpCM->addAction(act);
204 }
205 //Save the values for the next run
206 continent = info[i].section("::::",1,1);
207 country = info[i].section("::::",2,2);
208
209 if(i== info.length()-1){
210 //last go through - save all menus
211 if(tmpCM!=0 && tmpC!=0 && !tmpCM->isEmpty()){ tmpC->addMenu(tmpCM); }
212 if(tmpC!=0 && !tmpC->isEmpty()){ TZMenu->addMenu(tmpC); }
213 }
214 }
215
216 }
217
ThemeChange()218 void LClock::ThemeChange(){
219 TZMenu->setIcon(LXDG::findIcon("clock",""));
220 }
221
OrientationChange()222 void LClock::OrientationChange(){
223 if(this->layout()->direction()==QBoxLayout::LeftToRight){ //horizontal panel
224 //button->setRotation(0); //no rotation of text
225 this->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
226 button->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
227 }else{ //vertical panel
228 //button->setRotation(90); //90 degree rotation
229 this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
230 button->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
231 }
232 updateTime(true); //re-adjust the font/spacings
233 this->layout()->update();
234 }
235