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